Array Inizialisierung in const

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 7364
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Array Inizialisierung in const

Beitrag von Mathias »

Ist die zuverlässig, ich habe einen Stresstest gemacht, in dem ich die array oben fast in den 1GB-Bereich gebracht hatte.

Code: Alles auswählen

program project1;

type
  TMyRec = record
    arr: array[0..65535 * 2500] of Int32;
  end;

  procedure proc;
  const
    arr: TMyRec = ();
  var
    i: integer;
  begin
    Inc(arr.arr[0]);
    Write(arr.arr[0], ' ');
    for i := 1 to Length(arr.arr) - 1 do begin
      if arr.arr[i] <> 0 then begin
        WriteLn('Error: ', arr.arr[i]);
      end;
    end;
  end;

var
  i: integer;

begin
  for i := 0 to 60000 do begin
    proc;
  end;
end.
Was mich stutzig macht, ist dies Warnung:
project1.lpr(10,20) Warning: Some fields coming after "" were not initialized
Dateianhänge
2026-10-07_16-00.png
2026-10-07_16-00.png (6.32 KiB) 196 mal betrachtet
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Zvoni
Beiträge: 767
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Array Inizialisierung in const

Beitrag von Zvoni »

Ich glaube mich daran zu erinnern, dass eine Const-Deklaration innerhalb einer Prozedur nicht eine Konstante definiert, sondern eine statische Variable, welche beim verlassen/reentry der Prozedur ihre(n) vorherige(n) Wert(e) behält.
Von daher ist deine Verwendung mit Initialisierung in diesem Kontext eigentlich Unfug, da du eigentlich willst, dass die Variable ihre Werte vom vorherigen Durchlauf der Prozedur behält, welchem du mit der Initialisierung widersprichst.

"Const" in diesem Zusammenhang ist eine "unglückliche" Bezeichnung.

Was willst du eigentlich machen?

Proof of Concept

Code: Alles auswählen

program Project1;
{$mode ObjFPC}{$H+}
Function MyFunc(Const AReset:Boolean):Boolean;
Const Cnt:Integer=-4;
      i:Integer=0;
Begin
  If AReset Then i:=0;
  Writeln('Cnt=',Cnt,' - i=',i);
  Inc(Cnt);
  Inc(i);
  If i<5 Then Begin
    Result:=True;
    MyFunc(False)   //Recursive call
  end
  Else
    Result:=False;
End;
begin
  MyFunc(True);
  Writeln('Zweite Runde');
  MyFunc(True);
  Readln;
end.
ergibt

Code: Alles auswählen

Cnt=-4 - i=0
Cnt=-3 - i=1
Cnt=-2 - i=2
Cnt=-1 - i=3
Cnt=0 - i=4
Zweite Runde
Cnt=1 - i=0
Cnt=2 - i=1
Cnt=3 - i=2
Cnt=4 - i=3
Cnt=5 - i=4
Klar erkennbar, dass die Zeile "Const Cnt:Integer=-4;" nur beim absolut ersten Aufruf tatsächlich initialisiert, und bei nachfolgenden Aufrufen die Initialisierung ignoriert wird.

Dein Code

Code: Alles auswählen

procedure proc;
  const
    arr: TMyRec = ();
  var
wird also genau einmal beim ersten Aufruf in der Schleife auch tatsächlich mit "leer" initialisiert, und bei den restlichen 60000 Durchläufen ignoriert.

Heisst auch im Umkehrschluss:
Dein

Code: Alles auswählen

Inc(arr.arr[0]);
sollte in der Write-Zeile von 1 bis 60001 rennen.

Und solltest du WÄHREND der (äusseren) Schleife einen Wert im Array EINMALIG ändern (Bsp. arr.arr[42]:=42;), behält diese Array-Zelle diesen Wert in allen nachfolgenden Aufrufen.
heisst: Innerhalb deiner Prozedur solltest du dann ab dieser Zelle deine Fehlermeldung erhalten, welche jedesmal neu kommt bei den nachfolgenden Aufrufen der äusseren Schleife
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
Zvoni
Beiträge: 767
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Array Inizialisierung in const

Beitrag von Zvoni »

Was das hier betrifft:
Was mich stutzig macht, ist dies Warnung:
project1.lpr(10,20) Warning: Some fields coming after "" were not initialized
Hab das hier gefunden:
https://forum.lazarus.freepascal.org/in ... ic=60935.0
und das
https://www.freepascal.org/docs-html/ref/refse24.html
For constant records, each element of the record that you wish to initialize must be specified in the form Field: Value, separated by semicolons, and surrounded by round brackets.. You can omit fields that you don’t wish to initialize, in fact you can skip all fields. If you skip fields, the compiler will emit a warning.
Heisst: Die Warnung hat nichts per se damit zu tun, dass du eine leere Klammer angibst.
Es hat damit zu tun, dass der Compiler dich warnt, dass du Felder eines records in der Initialisierung weggelassen hast.
In diesem Sinne ist die leere Klammer sogar eher der Hinweis, dass du gar nicht initialisieren möchtest
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Mathias
Beiträge: 7364
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Array Inizialisierung in const

Beitrag von Mathias »

Code: Alles auswählen

"Const" in diesem Zusammenhang ist eine "unglückliche" Bezeichnung.
Dieser Meinung bin ich auch. Sowas wäre viel verständlicher., in den Classen kennt FPC dies jetzt schon.

Code: Alles auswählen

var
  i :Integer = 0; static;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten