C ist "freier" als Pascal

Für sonstige Unterhaltungen, welche nicht direkt mit Lazarus zu tun haben

Re: C ist "freier" als Pascal

Beitragvon Warf » 9. Aug 2017, 16:46 Re: C ist "freier" als Pascal

Mathias hat geschrieben:
Warum kann man Prozeduren keine statischen Arrays übergeben?

Bei mir geht dies
Code: Alles auswählen
procedure WriteArray(a: array of byte);
var
  i: integer;
begin
  for i := 0 to Length(a) - 1 do begin
    Write(a[i], ' ');
  end;
  WriteLn();
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  sa: array[50..100] of byte;
  i: integer;
begin
  WriteArray(sa);
  for i := Low(sa) to High(sa) do begin
    sa[i] := i;
  end;
  WriteArray(sa);
end;   

Dabei habe ich einen Nebeneffekt entdeckt, das die Werte der Arrray am Anfang undefiniert sind.


Hier hast du einen kleinen Fehler gemacht:deine Funktion WriteArray bekommt ein Argument eines Offenen Arrays. Dein array[50..100] of byte; ist ein Statischer Array. Beim Aufruf wird der statische Array dann umgewandelt in einen Offenen Array.

Wenn du wirklich einen Statisches Array übergeben willst, musst du dir dies erst als eigenen Typen definieren:
Code: Alles auswählen
type
  TByteArr50To100 = array[50..100] of Byte;


Dann kannst du es auch in Parametern verwenden, musst aber dann natürlich von Low nach High iterieren
Warf
 
Beiträge: 617
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Mathias » 9. Aug 2017, 17:05 Re: C ist "freier" als Pascal

Wenn du wirklich einen Statisches Array übergeben willst, musst du dir dies erst als eigenen Typen definieren:

Klar, wen die Array immer gleich gross ist, dann muss man natürlich einen Typ deklarieren, so wie es bei ein Record auch der Fall ist.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3255
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 9. Aug 2017, 18:28 Re: C ist "freier" als Pascal

Warf hat geschrieben:Wenn du wirklich einen Statisches Array übergeben willst, musst du dir dies erst als eigenen Typen definieren:


Ja, das hat mich auch schon gewundert:

Code: Alles auswählen
type
  dbuf = record
    ttim : TDateTime;
    vval : array[1 .. chnmax] of real;
  end;       
var
  datbuf : array[0 .. cdatmax - 1] of dbuf;
 


datbuf muss bei 0 beginnen, wenn ich es in einer Prozedur übergeben will. Aber vval arf bei 1 beginnen. ;-)
Timm Thaler
 
Beiträge: 439
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Timm Thaler » 9. Aug 2017, 20:42 Re: C ist "freier" als Pascal

Wie ist das eigentlich bei dynamischen Arrays: Wenn ich in einer Prozedur ein statisches Array datenbuffer : array[0..max] of real habe und das per LoadData(datenbuffer); an eine Prozedur übergebe, die mit procedure LoadData(var daten : array of real); deklariert ist, ist ja daten ein dynamisches Array von datenbuffer. Daten, die ich da reinschreibe, stehen nach Ende der Prozedur auch in datenbuffer.

Wird dabei ein neues Array daten angelegt und die Daten aus datenbuffer da rein und am Ende der Prozedur wieder zurückkopiert? Oder wird nur ein Zeiger auf datenbuffer übergeben? Was nebenbei eine vernünftige Erklärung wäre, warum die dynamischen Arrays immer bei Null anfangen.
Timm Thaler
 
Beiträge: 439
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 9. Aug 2017, 21:24 Re: C ist "freier" als Pascal

Timm Thaler hat geschrieben:Wie ist das eigentlich bei dynamischen Arrays: Wenn ich in einer Prozedur ein statisches Array datenbuffer : array[0..max] of real habe und das per LoadData(datenbuffer); an eine Prozedur übergebe, die mit procedure LoadData(var daten : array of real); deklariert ist, ist ja daten ein dynamisches Array von datenbuffer. Daten, die ich da reinschreibe, stehen nach Ende der Prozedur auch in datenbuffer.

Wird dabei ein neues Array daten angelegt und die Daten aus datenbuffer da rein und am Ende der Prozedur wieder zurückkopiert? Oder wird nur ein Zeiger auf datenbuffer übergeben? Was nebenbei eine vernünftige Erklärung wäre, warum die dynamischen Arrays immer bei Null anfangen.


Der Parameter ist immer noch ein Offenes Array und kein Dynamisches, Technisch wird es realisiert wie ein Statisches Array (also der Speicherblock der übergeben wird hat eine feste unveränderbare Länge, welche beim Aufruf feststehen muss), darum lassen sich Statische Arrays sehr leicht (implizit) in Offene Überführen, Dynamische Arrays allerdings nicht (grad gesehen: nur in Delphi, fpc konvertiert dir auch einen Dynamisches Array implizit). Wenn du nun das ganze als Referenz (var keyword) übergibst, so wird intern nur ein Zeiger auf das erste Element deines Statischen Arrays übergeben. (entspricht damit also der value übergabe eines Dynamischen arrays).

Es ist allerdings nicht so ganz wie ein Dynamisches Array, da ein Dynamisches Array sich da durch auszeichnet dass man SetLength aufrufen kann, was ja (logischerweise) nicht funktioniert

Wenn du einen Statischen Array einem Offenen Array per Value übergibst, so wird der gesamte Array bei der Übergabe kopiert, und ist dann im parameter als offenes Array 0 basiert, unabhängig von den ursprünglichen Arraygrenzen.

Außerdem kann man auch Teilarrays übergeben:
Code: Alles auswählen
procedure foo(arr: array of Byte);
...
 
var arr: Array[0..10] of Byte;
...
  foo(arr[1..5]); // übergibt einen array der Größe 5 mit den Elementen 1-5 des arrays arr


Dynamische Arrays fangen bei 0 an, damit sie mit der Zeigerarithmetik übereinstimmen, damit funktioniert dieser tolle Code:
Code: Alles auswählen
var p: PInteger;
  i: Integer;
begin
  p:=GetMem(5*SizeOf(integer));
  for i:=0 to 4 do
    p[i] := i;
  FreeMem(p);
end.


Da Dynamische Arrays somit Äquivalent zu Zeigern auf ein Array sind
Warf
 
Beiträge: 617
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 9. Aug 2017, 22:57 Re: C ist "freier" als Pascal

Warf hat geschrieben:Wenn du nun das ganze als Referenz (var keyword) übergibst, so wird intern nur ein Zeiger auf das erste Element deines Statischen Arrays übergeben... Wenn du einen Statischen Array einem Offenen Array per Value übergibst, so wird der gesamte Array bei der Übergabe kopiert, und ist dann im parameter als offenes Array 0 basiert, unabhängig von den ursprünglichen Arraygrenzen.


Das heisst, wenn ich nicht möchte, dass mein Array bei der Übergabe kopiert wird, sollte ich das immer mit var übergeben, auch wenn die Prozedur im Array nichts ändert. Klingt eigentlich logisch.
Timm Thaler
 
Beiträge: 439
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 9. Aug 2017, 22:59 Re: C ist "freier" als Pascal

Timm Thaler hat geschrieben:Das heisst, wenn ich nicht möchte, dass mein Array bei der Übergabe kopiert wird, sollte ich das immer mit var übergeben, auch wenn die Prozedur im Array nichts ändert. Klingt eigentlich logisch.


Nein, dafür gibt es das const Schlüsselwort. Damit wird ein Zeiger of das Objekt übergeben, allerdings jedwede Veränderung ausgeschlossen. Somit wird nur der Zeiger Kopiert (was die performance erhöht), aber gleichzeitig der Nebeneffekt das sich die Werte ändern können unterbunden.

Ohne keyword wiederum wird der Wert immer kopiert, dafür ist das Argument in der Funktion selbst dann als normale veränderbare Variable zur Verfügung. Wenn man die Werte nur lesen möchte, und die Daten größer als ein Pointer(64 Bit) sind, und die Performance relevant ist, sollte man immer const verwenden
Warf
 
Beiträge: 617
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Mathias » 10. Aug 2017, 17:25 Re: C ist "freier" als Pascal

Code: Alles auswählen
var
  p: ^Integer;
  i: integer;
begin
  p := GetMem(5 * SizeOf(integer));
  for i := 0 to 4 do begin
    p[i] := i;
  end;
 
  FreeMem(p);
end

Interessant, wie man den Integer-Pointer, als Array ansprechen kann. Sowas habe ich bis jetzt nie probiert, ausser bei Byte und Char.
Im Grunde, ist der PChar auch nichts anderes.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3255
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Warf » 10. Aug 2017, 17:54 Re: C ist "freier" als Pascal

Mathias hat geschrieben:
Code: Alles auswählen
var
  p: ^Integer;
  i: integer;
begin
  p := GetMem(5 * SizeOf(integer));
  for i := 0 to 4 do begin
    p[i] := i;
  end;
 
  FreeMem(p);
end

Interessant, wie man den Integer-Pointer, als Array ansprechen kann. Sowas habe ich bis jetzt nie probiert, ausser bei Byte und Char.
Im Grunde, ist der PChar auch nichts anderes.


Um ehrlich zu sein braucht man es auch nicht, arrays sind dank ihrer referenzzählung und dem der length Funktion eh viel angenehmer. So muss man nur arbeiten wenn man das letzte Bit optimieren möchte
Warf
 
Beiträge: 617
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

• Themenende •
Vorherige

Zurück zu Dies und Das



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried