Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi length(s) = 0 ODER s = '' ? (https://www.delphipraxis.net/65042-length-s-%3D-0-oder-s-%3D.html)

Master_RC 12. Mär 2006 04:32

Re: length(s) = 0 ODER s = '' ?
 
Nun gut, jetzt haben wir schon herausgefunden, was schneller ist (if s = ''), aber was ist sicherer?

Angel4585 12. Mär 2006 07:55

Re: length(s) = 0 ODER s = '' ?
 
nun das kommt darauf an was das Ganze bezwecken soll.. wenn nu ein Namensfeld hast wo Buchstaben drin stehen sollen und ein einfaches Leerzeichen ohne was dazu als leer zu betrachten ist dann ist trim schon die richtige variante, wenn nicht ist es egal was du nimmst, es dürfte alles genauso sicher sein.

jbg 12. Mär 2006 08:43

Re: length(s) = 0 ODER s = '' ?
 
Zitat:

Zitat von Master_RC
aber was ist sicherer?

Unter Delphi.Win32 ist beides gleich sicher, denn es ist nicht ohne Trickserei möglich, eienen String "mit" ohne Zeichen zu bekommen. Denn konvertiert man einen PChar in einen String, macht die Compilermagic automatisch NIL daraus, wenn der PChar leer ist. Wie folgender Code zeigt:
Delphi-Quellcode:
function GetP: PChar;
begin
  Result := #0;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  S: string;
begin
  S := GetP;
  if Pointer(S) = nil then
    ShowMessage('OK');
end;
Und bei einer Zuweisung von '' an eine String-Variable, wird die Variable automatisch auf NIL gesetzt.

Und wenn S = '' nicht immer funktionieren würde, hätte ich ein ziemlich großes Problem, was ich nicht habe.

negaH 13. Mär 2006 04:41

Re: length(s) = 0 ODER s = '' ?
 
was ist mit

Delphi-Quellcode:

var
  S: String;
begin
  S := 'A';
  S[1] := #0;

  if S <> '' then ;

  SetLength(S, 1);
  S[1] := #0;

end;
Gruß Hagen

thomasw 13. Mär 2006 05:25

Re: length(s) = 0 ODER s = '' ?
 
Mich wundert, dass der Compiler das nicht erkennt und entsprechend optimiert...

Robert Marquardt 13. Mär 2006 06:55

Re: length(s) = 0 ODER s = '' ?
 
Das kann nicht optimiert werden. Es ist ja explizit ein Puffer von 1 Zeichen fuer den String angefordert worden.
Der code funktioniert aber natuerlich. Es geht nur der initiale interne Test auf nil nicht. Der folgende String-Compare ergibt natuerlich wieder einen Leerstring.

SirThornberry 13. Mär 2006 06:58

Re: length(s) = 0 ODER s = '' ?
 
da es sich hierbei um einen String handelt würde "Length()" nicht 0 zurück geben (weil eben ein #0) vorhanden ist und der Vergleich mit "= ''" würde auch fehlschlagen weil eben etwas in dem String ist. Anders würde es bei einem PChar aussehen aber darum geht es ja hier nicht.

jbg 13. Mär 2006 09:01

Re: length(s) = 0 ODER s = '' ?
 
Zitat:

Zitat von thomasw
Mich wundert, dass der Compiler das nicht erkennt und entsprechend optimiert...

Was soll er denn da optimieren? Bei der ersten Zuweisung "S := #0" wird ein String generiert, der das #0-Zeichen enthält, also Length(S) = 1. StrLen(PChar(S)) hingegen würde 0 liefern, weil ein PChar auf #0 endet. Ein AnsiString/WideString endet aber nicht bei #0, sondern er endet da, wo der Puffer zu Ende ist, und das ist nach dem #0-Zeichen, was also eine Länge von 1 ergibt.
Das ist eben ein kleiner, aber feiner Unterschied zwischen PChar und String.

Unter .NET ist das aber wieder was anderes, da es dort in C# einen Unterschied macht, ob man S=NULL oder S="" schreibt. Ersteres wird als S:=nil interpretiert. Zweiteres hingegen als ein gültiges Leer-String Objekt. Man muss in .NET also immer auf beides prüfen: if (S != NULL && S != "") wenn man sicher gehen will, dass kein Null-String/Leer-String verarbeitet wird. Die Length() Funktion von Delphi fängt beide Fälle ab. In C# hingegen kracht es, wenn man S.length() aufruft, und S==NULL ist.

himitsu 13. Mär 2006 10:22

Re: length(s) = 0 ODER s = '' ?
 
Zitat:

Zitat von alcaeus
Ich wuerde auf zweiteres tippen, schliesslich muss beim ersten ja die Laenge berechnet werden. ;)

Greetz
alcaeus

Hab jetzt nicht alles durchgelesen, aber die Länge muß nicht erst berechnet werden, denn im String-Header steht die Länge schon drin.

S = '' und S <> '' sind dennnoch die schneller, denn diese sind intern nur Vergleiche auf
Pointer(S) = nil und Pointer(S) <> nil, wärend Length ein Funktionsaufrus ist, wo also nicht nur Verglichen, sondern ja auch erstmal zu der Funktion hin und wieder zurückgesprungen werden muß.

Wobei Length(S) = 0 also in etwas deinem Aufruf folgender Funktion gleicht:

Delphi-Quellcode:
Function Length(Const S: String): Integer;
  Begin
    If Pointer(S) = nil Then Begin
      Result := 0;
      Exit;
    End;
    Result := PInteger(@S - 4)^;
  End;
Was auch gleich klären sollte, warum der Aufruf von Length(Trim(S)) = 0 langsamer als nur Length(S) = 0 sein sollte, denn Trim ist ja 'ne StringOperation, we´lche intern selbst neben anderen Funktionsaufrufen das Length aufruft und nebenbei eventuell sogar noch Speicher reserviert, welche nach Length wieder freigegeben wird, außerden sind dazu auch noch Kopieroperationen im RAM zu beobachten, wenn etwas in S drin ist.


Ach ja, etwas zur inneren Funktion der Delphi-Strings/-Arrays:Theorätisch ist ein String auch nur ein dynamisches Array, was wiederum einem Pointer auf eine bestimmte Datenstrucktur entspricht.
Wobei diese Strucktir rein theoretisch ein Array mit der Länge 0 sein könnte, aber es wurde so gerägelt, das in diesem Fall das 0-Längen-Array freigegeben wird und der Pointer auf nil steht, weßhalb es S immer nil sein sollte.
Solange niemand absichtlich gegen diese Regel verstößt, was ich aber bisher noch nicht erlebt hab ... was aber auch sinlos wäre, da es sonst du netten Fehlern in vielen/ nahezu allen Delphifunktionen kommen würde, da diese Daten erwarten, wenn S <> nil ist ... es würde dann einfach, ohne ein weiteres Prüfen, ob die Längenangabe wirklich auf größer 0 steht auf den "nichtvorhandenen" Speicherbereich zugegriffen ;)


Und S := #0 ist ein String mit der Länge von einem Zeichen, wobei dieses Zeichen eben ein #0 ist ... in Strings wird eben nur auf die Längenangabe geachtet und ein #0 wird nicht als Stringende angesehen, weßhalb ich ja auch gerne mal einen String zur einfachen Aufnahme von Binärdaten verwende, da dem ja die #0 nichts anhaben kann :roll:


PS: die obrigen Angaben beziehen sich af ein natives Delphi und nicht auf .net.

runger 13. Mär 2006 10:39

Re: length(s) = 0 ODER s = '' ?
 
Hallo

Delphi-Quellcode:
  SetLength(S, 1);
  S[1] := #0;
eigentlich ist diese Anweisungskombination im eigentlichen Sinne nicht gültig.
Auf setlength, im Allgemeinen, bezogen gibts hier das Element S[1] garnicht.
Das ist bei Strings (in Delphi) anders hier besteht ein String aus einer Längenangabe
gefolgt von dem ersten Zeichen. Streng genommen erzeugt setlength(S,1) einen leeren
String mit der Länge 0.

Rainer


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

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-2025 by Thomas Breitkreuz