Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Prüfen, ob String ein Wert hat. Was ist schneller??? (https://www.delphipraxis.net/139717-pruefen-ob-string-ein-wert-hat-ist-schneller.html)

romber 3. Sep 2009 23:15


Prüfen, ob String ein Wert hat. Was ist schneller???
 
Beim parsen der XML-Daten, die ich über einen WebService erhalte muss ich oft prüfen, ob String-Variablen bereits Werte zugewiesen wurden. Dabei benutze ich Length-Funktion. Mann kann es auch mit String <> '' überprüfen. Welche Methode ist schneller?

Dax 3. Sep 2009 23:17

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Das müsste beides Äquivalent sein. Soweit ich weiss, wandelt Delphi den "<> ''" in ein "Length() > 0" um, und Length ist nur ein Speicherzugriff.

himitsu 4. Sep 2009 00:22

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
OK, mann könnte jetzt zwar denken, daß des Auslesen des Längen-Wertes und ein Integer-Vergleich flotter wären, als ein String-Verlgeich, aber ...


if S <> '' then und if S = '' then
ist eigentlich das Schnellste, denn dieses Prüft praktisch so
if Pointer(S) <> '' then
also ein einfacher Integer-Vergleich

das Andere dagegen ruft ja sozusagen eine Inline-Funktion auf

gegeben sei
Zitat:

var S: AnsiString;

if S <> '' then beep;
if S > '' then beep;
if Length(S) <> 0 then beep;
if Length(S) > 0 then beep;
raus kommt dieses:
Delphi-Quellcode:
Unit1.pas.30: if S <> '' then Beep;
00461B14 837DFC00         cmp dword ptr [ebp-$04],$00
00461B18 7405             jz $00461b1f
00461B1A E8D1D9FAFF      call Beep

Unit1.pas.31: if S > '' then Beep;
00461B1F 837DFC00         cmp dword ptr [ebp-$04],$00
00461B23 7605             jbe $00461b2a
00461B25 E8C6D9FAFF      call Beep

Unit1.pas.32: if Length(S) <> 0 then Beep;
00461B2A 8B5DFC          mov ebx,[ebp-$04]
00461B2D 8BC3             mov eax,ebx
00461B2F 85C0             test eax,eax
00461B31 7405             jz $00461b38
00461B33 83E804           sub eax,$04
00461B36 8B00             mov eax,[eax]
00461B38 85C0             test eax,eax
00461B3A 7405             jz $00461b41
00461B3C E8AFD9FAFF      call Beep

Unit1.pas.33: if Length(S) > 0 then Beep;
00461B41 8BC3             mov eax,ebx
00461B43 85C0             test eax,eax
00461B45 7405             jz $00461b4c
00461B47 83E804           sub eax,$04
00461B4A 8B00             mov eax,[eax]
00461B4C 85C0             test eax,eax
00461B4E 7E05             jle $00461b55
00461B50 E89BD9FAFF      call Beep
in Delphi2009/2010 kommt bei dem standardmäßig aktivierem StringChecking sogar sowas Monströses für diese einfachen Vergleiche/Funktionsaufrufe raus
Delphi-Quellcode:
Unit1.pas.28: if S <> '' then Beep;
00461B13 837DFC00         cmp dword ptr [ebp-$04],$00
00461B17 7405             jz $00461b1e
00461B19 E8D2D9FAFF      call Beep

Unit1.pas.29: if S > '' then Beep;
00461B1E 837DFC00         cmp dword ptr [ebp-$04],$00
00461B22 7605             jbe $00461b29
00461B24 E8C7D9FAFF      call Beep

Unit1.pas.30: if Length(S) <> 0 then Beep;
00461B29 8B45FC          mov eax,[ebp-$04]
00461B2C 85C0             test eax,eax
00461B2E 7418             jz $00461b48
00461B30 8BD0             mov edx,eax
00461B32 83EA0A          sub edx,$0a
00461B35 66833A01         cmp word ptr [edx],$01
00461B39 740D            jz $00461b48
00461B3B 8D45FC          lea eax,[ebp-$04]
00461B3E 33C9             xor ecx,ecx
00461B40 8B55FC          mov edx,[ebp-$04]
00461B43 E8EC32FAFF      call @InternalLStrFromUStr
00461B48 85C0             test eax,eax
00461B4A 7405             jz $00461b51
00461B4C 83E804           sub eax,$04
00461B4F 8B00             mov eax,[eax]
00461B51 85C0             test eax,eax
00461B53 7405             jz $00461b5a
00461B55 E896D9FAFF      call Beep

Unit1.pas.31: if Length(S) > 0 then Beep;
00461B5A 8B45FC          mov eax,[ebp-$04]
00461B5D 85C0             test eax,eax
00461B5F 7418             jz $00461b79
00461B61 8BD0             mov edx,eax
00461B63 83EA0A          sub edx,$0a
00461B66 66833A01         cmp word ptr [edx],$01
00461B6A 740D            jz $00461b79
00461B6C 8D45FC          lea eax,[ebp-$04]
00461B6F 33C9             xor ecx,ecx
00461B71 8B55FC          mov edx,[ebp-$04]
00461B74 E8BB32FAFF      call @InternalLStrFromUStr
00461B79 85C0             test eax,eax
00461B7B 7405             jz $00461b82
00461B7D 83E804           sub eax,$04
00461B80 8B00             mov eax,[eax]
00461B82 85C0             test eax,eax
00461B84 7E05             jle $00461b8b
00461B86 E865D9FAFF      call Beep

romber 4. Sep 2009 21:53

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Danke Euch! Also lieber doch mit String <> '' prüfen.

himitsu 4. Sep 2009 23:08

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
jupp,



wenn man mal bissl böse drauf ist, kann man auch sowas machen :oops:
Delphi-Quellcode:
if BOOL(s) then Beep;
// also statt  if s <> '' then Beep;

aber für sowas wäre es besser, wenn man auch weiß wie der String intern arbeitet
und warum dieses so überhaupt funktioniert.

im Endefekt gibt es aber nicht wirklich einen Vorteil und es kommt in der selbe Code raus,
(kein denn der Compiler optiert es im Prinzip auf diesen Code herrunter :coder: )
es sei denn man weiß sich sehr gut mit Absolute-Variablen zu helfen :nerd:

Dax 4. Sep 2009 23:15

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Also ist '' = nil?

Neutral General 4. Sep 2009 23:22

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Habs grad ausprobiert. Scheinbar schon.

jbg 4. Sep 2009 23:31

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Zitat:

Zitat von Dax
Also ist '' = nil?

Ja, solange man nicht einen nicht-nil Leerstring künstlich erzwingt. Sämtliche RTL Funktionen hätten mit so einem nicht-nil Leerstring jedoch Probleme weswegen man das gefälligst unterlassen sollte.

himitsu 4. Sep 2009 23:33

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
sagen wir es mal so

ein Leerstring entspricht bei einem String/WideString/AnsiString/UnicodeString einem NIL
(wie schon jbg sagte, ist das der Normalzustand ... und wer daran rumbastelt, hat mit den Konsequenten zu leben)

sobald Inhalt vorhanden ist, wird Speicher reserviert und er zeigt auf diesen Speicher
am Referenzzähler kann man sogar noch viel mehr erkennen ... z.B.
> ist es eine Variable oder eine Konstante (nicht zu verwechseln mit Const-Parameter)
> wenn es eine Variable ist, wie oft wird sie in diesem Moment verwendet


ich nutze dieses manchmal gerne aus

z.B. wollen ja einige WinAPI-Strukturen entweder NIL oder Inhalt
(z.B. bei den OpenDialogen)
Delphi-Quellcode:
A = Record    A.P = PChar

// also statt

FillChar(A, Size, 0);
if S <> '' then A.P := PChar(S);

// oder

if S <> '' then
  A.P := PChar(S)
Else
  A.P := nil;

// einfach nur

A.P := Pointer(S);


ABER PChar(s) zeigt immer auf Speicher,
da dieses keine Typkonvertierung darstellt, sondern eine virtuelle Funktion der Compiler-Magic
Delphi-Quellcode:
Function PChar(const s: String): PChar;
  Const i: Integer = 0;

  Begin
    If S <> '' Then Result := Pointer(S) Else Result := @i;
  End;

Neutral General 4. Sep 2009 23:40

Re: Prüfen, ob String ein Wert hat. Was ist schneller???
 
Wobei ich dann nicht verstehe was das bringen soll. Warum dann nicht

Delphi-Quellcode:
else Result := nil;
? Das wäre sogar noch kompatibler....


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:50 Uhr.
Seite 1 von 2  1 2      

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