Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Vorsicht! statisches Array mit Startindex>0 (https://www.delphipraxis.net/184114-vorsicht-statisches-array-mit-startindex-0-a.html)

Photoner 27. Feb 2015 13:42

Delphi-Version: XE5

Vorsicht! statisches Array mit Startindex>0
 
Hi!
Es gibt die Möglichkeit statische Arrays (Typ egal) bei z.B. bei Index 1 anfangen zu lassen. Macht man dies und greift in einer Schleife- weil man es gewöhnt ist und es schneller zu tippen ist- mit Startindex 0 zu, liefert das dann falsche Werte. Halte ich für brandgefährlich.
Vieleicht ist das für viele eine olle Kamelle, aber mir war das so nicht bewusst und ich werde in Zukunft lieber mit Low() und High() arbeiten und würde dies auch jedem empfehlen.

Codebeispiel Konsolenanwendung:

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  Arr : Array [1..2] of Boolean;
  i  : Integer;
begin
  try
    { TODO -oUser -cConsole Main : Code hier einfügen }
    Arr[1] := True;
    Writeln(BoolToStr(Arr[1]));
    Arr[2] := True;
    Writeln(BoolToStr(Arr[2]));
    Writeln('');
    //Writeln(BoolToStr(Arr[0])); // Zur Kompilierzeit [dcc32 Fehler] Project1.dpr(20): E1012 Konstantenausdruck verletzt untere Grenzen
    for I := 0 to High(Arr) do
      Writeln(BoolToStr(Arr[i]));
    Writeln('');
    for I := Low(Arr) to High(Arr) do
      Writeln(BoolToStr(Arr[i]));
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Ergibt:
-1
-1

0
-1
-1

-1
-1

Sir Rufo 27. Feb 2015 13:51

AW: Vorsicht! statisches Array mit Startindex>0
 
Brandgefährlich ist es auch ein Sprung vom 5-Meter-Turm ohne sich vergewissert zu haben, dass sich ausreichend Wasser im Becken befindet :roll:

Du kannst bei den Optionen die Bereichsprüfung einschalten, dann schmeisst dir der Compiler um die Ohren und schwups ist der brand gelöscht (hat es gebrannt?)

Mavarik 27. Feb 2015 13:52

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Photoner (Beitrag 1291712)
Halte ich für brandgefährlich.

emm nicht dein Ernst....

Wie definierst Du den Array für die Tage in einem Monat?

Array[1..31]
Oder
für andere Werte
Array[-7..7]

Das dynamiche Arrays immer bei Null anfangen ist eher läßtig und bring noch eine ganz andere Gefahr mit:

Beispiel:

Delphi-Quellcode:
type
   TA : Array of Ansichar;
   TB : Array [0..200] of Ansichar;
var
  A : TA;
  B : TB;
  S : Shortstring;
begin
  S := 'Cooler Text';
  Setlength(A,201);

  Move(S[1],A,length(S));
  Move(S[1],B,length(S));
end;
Na wer findet die Exception?

Mavarik

Der schöne Günther 27. Feb 2015 13:55

AW: Vorsicht! statisches Array mit Startindex>0
 
Hier ein etwas kürzeres Beispiel:
Delphi-Quellcode:
program Project22;

{$APPTYPE CONSOLE}
uses System.SysUtils;

type
   TStaticArray = array[5..10] of Integer;

var
   meinArray:   TStaticArray;
   arrayIndex:   Integer;
begin
   for arrayIndex := -5 to 99 do
      WriteLn( meinArray[arrayIndex] );
end.
Ohne mich dem Spott anschließen zu wollen:

Ja, eigentlich sollte man immer mit Low() und High() arbeiten statt magische Zahlen hinzutippen.
Und ja, wenn man die Bereichsprüfung aus hat bekommt man zur Laufzeit keinen Fehler.

Aber man sollte trotzdem anmerken dass es wirklich etwas ernüchternd ist dass der Compiler für so etwas offensichtliches keine Warnung ausgeben kann.

Bernhard Geyer 27. Feb 2015 13:58

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Photoner (Beitrag 1291712)
Vieleicht ist das für viele eine olle Kamelle,

Ist es. Das ist ein feature der Sprache Pascal sowas zu können. Andere Sprachen können sowas nicht und deshalt macht man dort immer ein for 0 ... count-1 (Außgenommen jetzt moderne sprache wo man ein for-each-Schleife hat).

himitsu 27. Feb 2015 14:03

AW: Vorsicht! statisches Array mit Startindex>0
 
Doch, der Compiler/Programm kann "Exceptions" werfen, aber wenn du die Bereichsprüfung nicht aktivierst... :roll:
[edit] siehe Sir Rufo

Und dann natürlich die genannten For-In und Low-High.
Delphi-Quellcode:
for i in meinArray do
  WriteLn(i);
Dafür kennt Delphi keine leeren/undefinierten statischen Arrays ala
Delphi-Quellcode:
array[0]
und man sieht öfters mal ein
Delphi-Quellcode:
array[0..0]
, wo man es ja will, daß man über die 0 hinaus kann.

Photoner 27. Feb 2015 15:20

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Sir Rufo (Beitrag 1291715)
Du kannst bei den Optionen die Bereichsprüfung einschalten, dann schmeisst dir der Compiler um die Ohren und schwups ist der brand gelöscht (hat es gebrannt?)

Danke für den Hinweis. Jetzt weiß ich dass es beim Anlegen von neuen Projekten aus ist. (Lässt sich aber bestimmt einstellen)

Zitat:

Zitat von Sir Rufo (Beitrag 1291715)
Brandgefährlich ist es auch ein Sprung vom 5-Meter-Turm ohne sich vergewissert zu haben, dass sich ausreichend Wasser im Becken befindet :roll:


Warum dieser Sarkasmus? Habe ich was falsches gemacht als ich das für andere Programmierende, die auch nicht so viel Erfahrung haben wie ihr, erwähnt habe?
Denk mal darüber nach wie viel Spaß das aktive Teilnehmen im Forum noch für Anfänger macht wenn sich die Altherrenrunde über mich und andere so lustig macht.


Zitat:

Zitat von Mavarik (Beitrag 1291716)

Delphi-Quellcode:
type
   TA : Array of Ansichar;
   TB : Array [0..200] of Ansichar;

emm nicht dein Ernst....

Zitat:

Zitat von Mavarik (Beitrag 1291716)

Delphi-Quellcode:
  Move(S[1],A,length(S));

Sollte wohl eher so aussehen:
Delphi-Quellcode:
Move(S[1],A[0],length(S));
und was willst du damit sagen?

Mavarik 27. Feb 2015 15:28

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Photoner (Beitrag 1291741)
Sollte wohl eher so aussehen:
Delphi-Quellcode:
Move(S[1],A[0],length(S));

Ach wieso den?

Delphi-Quellcode:
Move(S[1],B,length(S));
Funktioniert doch...
Zitat:

Zitat von Photoner (Beitrag 1291741)
und was willst du damit sagen?

SO eine Änderung ist brachgefährlich...

Eigentlich müsste es bei Dynamischen Array immer mit ^ geschrieben werden, da es sich nicht mehr um Speicherbereich handelt,
sondern plötzlich um einen "Zeiger"...

Mavarik

Uwe Raabe 27. Feb 2015 15:47

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Mavarik (Beitrag 1291744)
SO eine Änderung ist brachgefährlich...

Eigentlich ist das MOVE gefährlich, da es nicht typ-sicher ist. Deshalb muss man bei der Verwendung von solchen Low-Level-Dingen halt besonders aufpassen.

himitsu 27. Feb 2015 17:23

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1291748)
Eigentlich ist das MOVE gefährlich, da es nicht typ-sicher ist. Deshalb muss man bei der Verwendung von solchen Low-Level-Dingen halt besonders aufpassen.

Dafür gibt es ja inzwischen z.B. TArrayManager<T>.Move / TMoveArrayManager<T>.Move

p80286 27. Feb 2015 18:25

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Mavarik (Beitrag 1291716)
Delphi-Quellcode:
type
   TA : Array of Ansichar;
   TB : Array [0..200] of Ansichar;
var
  A : TA;
  B : TB;
  S : Shortstring;
begin
  S := 'Cooler Text';
  Setlength(A,201);

  Move(S[1],A,length(S));
  Move(S[1],B,length(S));
end;

Mit Deinem coolen Text mag das ja noch funktionieren, aber wenn er richtig lange cool wird ist ein
Delphi-Quellcode:
TB : Array [0..254] of Ansichar;
wohl eher angebracht. Wobei ich ein [1..255] bevorzuge, weil dann der Index synchron laufen kann.

Gruß
K-H

Der schöne Günther 27. Feb 2015 18:36

AW: Vorsicht! statisches Array mit Startindex>0
 
Ich habe noch nicht einmal eine ungefähre Ahnung was euer Code machen soll, aber ich bin mir sicher etwas Assembler würde ihm noch den letzten Schliff verleihen.

himitsu 27. Feb 2015 18:46

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von p80286 (Beitrag 1291772)
Wobei ich ein [1..255] bevorzuge, weil dann der Index synchron laufen kann.

ShortString :stupid:

Und rate mal, was passiert, wenn du mal auf einen NextGen-Compiler triffst.
> String-Indize beginnen dort bei 0

Bzw. die neuen String-Helper indizieren immer mit 0 beginnend.


Viele Dinge wurden um 2006 durch die FastCodeLibrary ersetzet.
Wenn da auch Move dabei war (so wie z.B. die Move's im FastMM), dann ist das schon optimiert und kopiert auch schonmal mit 4 bis 16 Bytes pro Loop.

Assembler ist nicht immer besser, vorallem wenn man sich selber nicht mit den Cache- und Pfadvorhersagemechianismen der "aktuellen" Prozeduren auskennt.

p80286 28. Feb 2015 11:34

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von himitsu (Beitrag 1291780)

Und rate mal, was passiert, wenn du mal auf einen NextGen-Compiler triffst.
> String-Indize beginnen dort bei 0

Na dann stellt man sich eben um, ein bischen Flexibilität hat noch keinem geschadet.

Gruß
K-H

Bernhard Geyer 28. Feb 2015 12:27

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von p80286 (Beitrag 1291851)
Zitat:

Zitat von himitsu (Beitrag 1291780)

Und rate mal, was passiert, wenn du mal auf einen NextGen-Compiler triffst.
> String-Indize beginnen dort bei 0

Na dann stellt man sich eben um, ein bischen Flexibilität hat noch keinem geschadet.

Da nimmt man halt die String-Helper Methoden und man hat wieder einen Quellcode für beide Welten.
Statt Flexibilität muss man halt den Quellcode (nachdem er von Pascal 1 (?) bis XE8 (WinX/OSX) ohne änderung funktionieren würde) umstellen.

SMO 28. Feb 2015 15:31

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von Mavarik (Beitrag 1291744)
Eigentlich müsste es bei Dynamischen Array immer mit ^ geschrieben werden, da es sich nicht mehr um Speicherbereich handelt,
sondern plötzlich um einen "Zeiger"...

Dann müsstest du auch strings immer mit ^ schreiben, denn die sind nichts anderes als dynamische Arrays of Char. :stupid:

Also ich bin froh, dass man ^ mittlerweile in vielen Fällen (z.B. Zugriff auf Felder eines Record-Pointers) weglassen kann.


Zitat:

Zitat von Mavarik (Beitrag 1291716)
Na wer findet die Exception?

Also wenn schon, dann richtig:
Delphi-Quellcode:
uses
  System.Math;

type
  TA = Array of AnsiChar;
  TB = Array [0 .. 200] of AnsiChar;

var
  A: TA;
  B: TB;
  S: ShortString;

begin
  S := 'Cooler Text';
  SetLength(A, 201);

  Move(S[Low(S)], A[Low(A)], Min(Length(S) * SizeOf(S[Low(S)]), Length(A) * SizeOf(A[Low(A)])));
  Move(S[Low(S)], B[Low(B)], Min(Length(S) * SizeOf(S[Low(S)]), Length(B) * SizeOf(B[Low(B)])));
end;
So funktioniert es mit statischen und dynamischen Arrays, unabhängig vom Startindex. Nur nicht mit ShortString, weil Low() hier eben 0 liefert und damit nach dem Move #11'CoolerTex' in A und B steht. Besoders schön / leserlich ist solcher Code natürlich auch nicht. ;)

Mavarik 1. Mär 2015 02:03

AW: Vorsicht! statisches Array mit Startindex>0
 
Zitat:

Zitat von SMO (Beitrag 1291863)
Dann müsstest du auch strings immer mit ^ schreiben, denn die sind nichts anderes als dynamische Arrays of Char. :stupid:

Nur wenn es keine Shortstrings sind... Da sich bei einem ShortString wieder Speicher dahinter "versteckt"

Zitat:

Zitat von SMO (Beitrag 1291863)
Also wenn schon, dann richtig:

Es ging nicht darum es richtig zu machen, sondern eine "möglichen" Fehlerquelle auf zu zeigen... :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz