Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Schleifenvariable beschreiben, ... (https://www.delphipraxis.net/137349-schleifenvariable-beschreiben.html)

Corpsman 19. Jul 2009 09:59


Schleifenvariable beschreiben, ...
 
Guten Morgen,

Ich höre ja gerade eine Vorlesung über Konzepte von Programmiersprachen.

Und unser Prof zeigt uns immer mal wieder echt "Überraschende" dinge.

Das Konstanten keine Konstanten sind hatte ich ja auch schon mal geschrieben.

Heute zeige ich euch wie man Schleifenvariablen werte zuweisen kann.

Ja richtig gelesen, das geht. Obwohl es eigentlich nicht erlaubt ist.

Und wie auch schon bei den Konstanten lautet der Trick hier wieder , POINTER.

Es scheint als habe Delphi ( zumindest D5Pro ) keinerlei Pointer Optimierung, bzw. Pointer Prüfungen.

Folgender Code ist in D5 Legal und sorgt für eine Endlosschleife.

Testet doch bitte in euren D5 versionen ob der Code Legal ist und ob das selbe passiert ;).

Delphi-Quellcode:

Procedure TForm1.Button1Click(Sender: TObject);
Var
  x: Integer;
  p: ^integer;
Begin
  p := @x;
  For x := 0 To 3 Do Begin
    showmessage(inttostr(x));
    p^ := 1;
  End;
End;
Also aufgepasst. Jeder der sich ein Programm schreibt das Pointer benutzt. Eure schleifen könnten evtl. ewig laufen *g*

jaenicke 19. Jul 2009 10:00

Re: Schleifenvariable beschreiben, ...
 
Wenn du mit Pointern herumspielst, dann musst du auch wissen was du tust. Wenn nicht, dann hast du eben Pech. ;-)

himitsu 19. Jul 2009 10:05

Re: Schleifenvariable beschreiben, ...
 
Zitat:

Das Konstanten keine Konstanten sind hatte ich ja auch schon mal geschrieben.
nicht alle

Zitat:

Heute zeige ich euch wie man Schleifenvariablen werte zuweisen kann.
Ja richtig gelesen, das geht. Obwohl es eigentlich nicht erlaubt ist.
und das weiß ich schon lange, aber sowas macht man nicht, denn ein kleiner Fehler und die Abbruchbedingung der Schleife wird nicht mehr erfüllt.

Hatte ich mal, als ich eine Schleife in 3er-Schritten zählen lassen wollte

quasi:
Delphi-Quellcode:
For x := 0 to 10 step 3 do
  ...
also
Delphi-Quellcode:
For x := 0 to 10 do Begin
  ...
  Inc(PInteger(@x), 3);
End;
und wer richtig hinsieht, wird schnell erkennen, daß die 10 nie nicht getroffen wird und es somit zum Überlauf kommt - 0, 3, 6, 9, 12, 15... - nachdem der Integer-Wertebereich dann zum drittenmal durchlaufen wurde, dann trifft er hier zufällig mal die 10 :angel2:

Und ja, Delphi (alle Versionen) hat da keine Pointer-Prüfung drin.

[edit]
jatzt mach ich schon statt Quote-Tags überall Delphi-Tags :shock:

mkinzler 19. Jul 2009 10:06

Re: Schleifenvariable beschreiben, ...
 
Saubere Programmierung scheint mir sowieso out zu sein :gruebel:

himitsu 19. Jul 2009 10:09

Re: Schleifenvariable beschreiben, ...
 
Zitat:

Zitat von mkinzler
Saubere Programmierung scheint mir sowieso out zu sein :gruebel:

sagen wir es mal so, ich bin vor 4 oder 5 Jahren mal auf diesen "Trick" gekommen und ich nutze es in keinem aktiven Programm mehr.

Auch wenn ich in anderen Dingen wohl auch nicht sooooo braf bin und den offiziellen Weg geh. :angel2:

mkinzler 19. Jul 2009 10:14

Re: Schleifenvariable beschreiben, ...
 
Hallo Frank, du hast dich einfach so dazwischen geschoben, die Aussage war nicht an dich gerichtet.
Es gibt wohl Probleme, die "dreckig" gelöst werden wollen, bzw bei denen eine solche Lösung im Moment besser (erscheint) oder hilft scnhell weiterzukommen. in den meisten Fällen ist es aber besser eine saubere Lösung zu finden.
Dazu sollte man aber genau wissen, was man macht und im Hinterkopf behalten, dass bei einer neuen version des Compilers oder sogar nach einem Patch die ganze Sache nicht mehr funktionieren könnte.

Corpsman 19. Jul 2009 12:34

Re: Schleifenvariable beschreiben, ...
 
@jaenicke

Irgendwie hab ich das Gefühl, das ich misverstanden wurde.

Mir ist schon klar was Pointer können, und was sie anrichten. Dieser Thread galt mehr als !Achtung! Pointer können auch viel Blödsinn anstellen.

Gerade in der Theorie ist es wichtig das man weis, das eine Schleife immer Terminiert. Und das hier gezeigte Beispiel sollte lediglich zeigen, das dies in Delphi per se nicht der Fall ist.

Luckie 19. Jul 2009 13:40

Re: Schleifenvariable beschreiben, ...
 
Zitat:

Zitat von Corpsman
das eine Schleife immer Terminiert. Und das hier gezeigte Beispiel sollte lediglich zeigen, das dies in Delphi per se nicht der Fall ist.

Wie kommst du darauf, dass eine Schleife immer terminiert? bei einer while-Schleife muss nur die Abbruchbedingung nicht stimmen und die Schleife wird nicht terminieren.

Davon mal abgesehen, war dein Beispiel wohl schon allgemein bekannt. ;)

Reinhard Kern 20. Jul 2009 01:34

Re: Schleifenvariable beschreiben, ...
 
Zitat:

Zitat von himitsu
[
Delphi-Quellcode:
For x := 0 to 10 do Begin
  ...
  Inc(PInteger(@x), 3);
End;
und wer richtig hinsieht, wird schnell erkennen, daß die 10 nie nicht getroffen wird und es somit zum Überlauf kommt - 0, 3, 6, 9, 12, 15... - nachdem der Integer-Wertebereich dann zum drittenmal durchlaufen wurde, dann trifft er hier zufällig mal die 10 :angel2:

Hallo,

das ist aber unsaubere Programmierung durch den Compiler selbst: jeder Anfänger weiss oder merkt es mal, dass man Abbruchbedingungen möglichst nicht mit =, sondern mit < oder > machen sollte, Grund siehe oben. Ich nenne das defensives Programmieren.

Aber wie schon bemerkt, sowas ist ja out.

Gruss Reinhard

himitsu 20. Jul 2009 04:44

Re: Schleifenvariable beschreiben, ...
 
For hat aber anscheinend ein = als Abbruchbedingung ud als Startbedingung ein >= bzw. <=

und jupp eine kleines While-Schleifchen und alles ist Gut :angel2:

Medium 20. Jul 2009 06:27

Re: Schleifenvariable beschreiben, ...
 
Vorsicht ist hier dennoch geboten. Je nach Verwendung der Schleifenvariable macht der Compiler unterschiedliche Dinge bei der Optimierung. So wird auch gerne mal eine "for x=N to K" Schleife im Kompilat zu einer "for x=(K-N) downto 0" Schleife, da eine Prüfung auf 0 i.A. schneller ausfällt als eine auf beliebige Zahlen. Wenn man dann das Register von x auf solche Weise inkrementiert kann man sich vorstellen dass es ziemlich hässlich wird.

Wenn man sowas wie stepping in Delphi braucht, nimmt man sich am besten eine while- oder repeat-Schleife her. Die ist dann auch nicht viel langsamer, dafür aber gesichert richtig. Und die zwei Zeilen mehr im Code sind es denke ich nun wirklich nicht wert da seltsame Dinge zu tun um sie zu vermeiden.

Ich bin ja auch ein Freund von Dingen die man nicht tut, bzw. Fummelein die Möglichkeiten eröffnen. Aber in "ernsthaften" Projekten hat sowas 0,nix verloren. Das sind Dinge die schön zu wissen sind, anwenden: Besser nicht.

himitsu 20. Jul 2009 06:49

Re: Schleifenvariable beschreiben, ...
 
Da hier ein Pointer auf die Variable geholt wird, macht der Compiler eigentlich keine diesbezüglichen Optimierungen.

mkinzler 20. Jul 2009 07:01

Re: Schleifenvariable beschreiben, ...
 
Es ist nur die Frage was passiert, wenn der Compiler aus Performancegründen die Laufrichtung umdrehet und man manuelle den Zähler erhöht

himitsu 20. Jul 2009 07:11

Re: Schleifenvariable beschreiben, ...
 
Das macht er nur, wenn innerhalb der Schleife nicht direkt auf die Zählervariale zugegriffen, bzw. wenn sie garnicht verwendet wird.

Aphton 20. Jul 2009 10:26

Re: Schleifenvariable beschreiben, ...
 
Zitat:

Zitat von Medium
Wenn man sowas wie stepping in Delphi braucht, nimmt man sich am besten eine while- oder repeat-Schleife her.

Das muss nicht unbedingt sein.
Ein einfaches "continue" tuts auch :D

Delphi-Quellcode:
  for i := 0 to 10 do
  begin
    if not( i mod 2 = 0) then
      Continue;
    ShowMessage( 'Nur gerade Zahlen :D [' + inttostr(i) + ']' );
  end;
MfG

himitsu 20. Jul 2009 10:34

Re: Schleifenvariable beschreiben, ...
 
wenn dann eher so
Delphi-Quellcode:
for i := 0 to 5 do
begin
  i2 := i * 2
  ShowMessage( 'Nur gerade Zahlen :D [' + inttostr(i2) + ']' );
end;
geh mal mindestens in Tausendershritten ... da wäre das sehr unökonomisch die Schleife je 9999 mal anzufangen und nur je einmal abzuarbeiten :angel2:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:26 Uhr.

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