![]() |
TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Nachdem ich ewig lange recherchiert habe, wie man komplette Ordnerinhalte kopiert (alle Dateien und Unterordner), habe ich nicht wirklich herausfinden können, wieviele Null-Terminatoren bei den Pfaden im TSHFileOpStruct benötigt werden.
![]() Manche Codes im INet benutzen TStrings oder AnsiString, andere benutzen TFileName. Die einen terminieren pFrom und pTo überhaupt nicht zusätzlich, andere mit 1 zusätzlichen #0, und wiederum andere mit 2 zusätzlichen #0. Erstaunlicherweise sind die meisten Beiträge, die ich dazu gefunden habe, aus den frühen 2000er Jahren. Da ist ja viel Zeit vergangen. Wie sieht das denn heute aus? Welcher Eingangs-Dateityp (für Source- und Destination-Path) muss mit wie vielen Terminatoren ergänzt werden, wenn er mit PChar() an pFrom und pTo übergeben wird? Im Moment benutze ich den folgenden Code, der TFileName als Typ für Source und Destination verwendet. Dabei werden keine zusätzlichen Null-Terminatoren benutzt. Ist das überhaupt in Ordnung? Leider konnte ich diesbezüglich keine Informationen zu TFileName finden.
Delphi-Quellcode:
Guido.
// Routine zum Kopieren von Dateien und Ordnern.
function SHCopyFile(Handle: THandle; szSource, szDestination: TFileName): Boolean; var ShellFileOperation: TSHFileOpStruct; begin Result := True; try with ShellFileOperation do begin Wnd := 0; wFunc := FO_COPY; pFrom := PChar(szSource); pTo := PChar(szDestination); fFlags := FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION; end; SHFileOperation(ShellFileOperation); except Result := False; end; end; |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Eigentlich steht alles in dem verlinkten MS-Artikel drin:
Zitat:
Im Delphi würde ich das wohl so machen:
Delphi-Quellcode:
denn IIRC hängt der Cast zu PChar bereits ein NULL an.
PChar(szSource + #0);
Grüße Dalai |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Delphi hängt standardmäßig immer zwei Nullen an seine Strings an. (als Kompatibilität auch zu solchen Listen)
Also im Prinzip könnte man es hier auch weglassen, aber zur Dokumentation hänge ich auch meistens die richtige Anzahl der Nullen nochmals an, also diese #0#0 für Listen. (nur bei "einfachen" PChars lasse ich diese #0 weg) Und ja, hier sind es "eigentlich" zwei #0, denn es ist eine Liste von Pfaden, wobei als Listenende ein Leerstring definiert ist.
Delphi-Quellcode:
, also effektiv #0#0 am Ende.
'Datei1'#0 + 'Datei2'#0 + {ENDE} ''#0;
PS: Die RTTI nutzt sowas ebenfalls, z.B. bei der Namensliste für ENUMs, oder die StringListen in den Ressources. PS: ein PChar-Cast, von einem String aus, gibt immer einen "gültigen" Zeiger zurück. Ein leerer String ist zwar NIL, aber hier wird dann ein Zeiger auf eine Konstante mit #0#0 zurückgegeben. Wer für eine Funktion ein "echtes" NIL benötigt, wenn der String leer ist, der sollte mit Pointer casten
Delphi-Quellcode:
statt
Pointer(MyString)
Delphi-Quellcode:
.
PChar(MyString)
(einziger Nachteil des Pointer, dabei geht die Typprüfung bezüglich ANSI und Unicode verloren) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Wie viele #0's ergibt das denn?
PChar(szSource + #0);
Gibt es denn auch "zuviele" #0's? Wenn ein string in Delphi schon standardmäßig 2 #0 hat und ich z. B. eingebe:
Delphi-Quellcode:
Kann es dann passieren, dass pFrom nun 4 #0 am Ende hat, und die Funktion das als Leerstring für pTo auswertet?
pFrom := PChar(szSource + #0#0);
pTo := PChar(szDestination + #0#0); Wie sieht das denn mit TFileName aus, also mit wie vielen #0's ist TFileName abgeschlossen? |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
. Strings sind in Delphi AFAIK nicht nullterminiert (sie haben aber im Gegensatz zu nullterminierten Strings eine Längenangabe).
string
Grüße Dalai |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
PChar(szSource + #0) ==> Wie viele #0's ergibt das denn? ==> Mindestens zwei.
Gibt es denn auch "zuviele" #0's? ==> Kommt auf den Anwendungszweck an. Meistens nein, und in diesem Fall definitiv nicht. Kann es dann passieren, dass pFrom nun 4 #0 am Ende hat, und die Funktion das als Leerstring für pTo auswertet? ==> Nein. Wie bei MS beschrieben, liest die API-Funktion bis zum ersten doppelten NULL und stoppt dort. Die Einzelstrings sind mit einfachen NULLs voneinander getrennt. ... mit wie vielen #0's ist TFileName abgeschlossen? ==> TFileName ist nur ein Alias für einen
Delphi-Quellcode:
. Strings sind in Delphi AFAIK nicht nullterminiert (sie haben aber im Gegensatz zu nullterminierten Strings eine Längenangabe).
string
@Dalai Vielen Dank für die deutlichen Aussagen! :) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Jain.
Delphi-Strings sind per-se nicht null-terminiert, da ihre Länge gespeichert und von Delphi verwendet wird. Beim ShortString (dem "String" aus TurboPascal und dem ersten Delphi) gibt es nur das Längen-Byte und keine explizite #0 am Ende. Bei den LongStrings (AnsiString/UTF8String/RawByteString/... und UnicodeString) gibt es aber als Optimierung auch die #0#0 am Ende, damit es ohne umkopieren direkt nach PChar gecastet werden kann. Der WideString ... OLE32-String ( ![]() Also Delphi/Pascal verwendet bei String-Operationen nur die Längenangabe, aber bei der Verwaltung wird hinter dem letzten Zeichen noch ein Bereich mit den #0#0 bereitgehalten. Beispiel: StrLen im C++ liest den String Zeichen für Zeichen und sucht die erste #0 (Ende-Anfang=Länge), während Length direkt den Längen-Integer ausliest. |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
function SHCopyFile(Handle: THandle; szSource, szDestination: TFileName): Boolean; ... pFrom := PChar(szSource + #0); pTo := PChar(szDestination + #0); Vielen Dank für eure Infos! :) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
TFileName ist kein Alias, es ist ein Nachfahre. :zwinker:
Delphi-Quellcode:
Definiert einen neuen Typ mit den selben Eigenschaften, welcher auch zuweisungskompatibel ist.
type
TFileName = type string; ^^^^ String ist sowas, wie Integer früher und NativeInt jetzt ist ... er ist ein Alias auf den nativen Typen des Compilers. * vor Delphi2009 war es der AnsiString * und gaaaaaanz früher war es kein Alias, da war es der Typ String, welcher jetzt ShortString heißt (aber der Einfachheit halber könnte man es da als Alias für den ShortString sehen) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Debug es doch und lass dir anzeigen, was in den Variablen drin steht.
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Luckie, du bist der Beste! :thumb: Die ganze Zeit habe ich überlegt, wie ich das damals anzeigen lassen habe und bin nicht aufs Debuggen gekommen. Kennst du das, wenn du weißt, da war doch was, aber du kommst nicht drauf was? :gruebel: Auch wenns leider nicht funktioniert, (siehe Screenshot), weiß ich jetzt wenigstens was mir nicht mehr einfallen wollte! Vielen Dank.
Ich weiß aber auch, dass das damals ging, da wurde im Tooltip über den Variablen auch die #0's angezeigt. Muss ich noch irgendwas einstellen, damit das angezeigt wird? |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Genau! :-D Bei mir wars Turbo Delphi 2006! Hach ja, die alten Zeiten. ...
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Hast du eine Idee, warum bei mir kein #0 angezeigt wird? (siehe Screenshot weiter oben)
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Hallo,
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Nachtrag: Halt, Kommando zurück! Da gab es ein Missverständnis meinerseits. Ich hatte im Kopf, dass die #0's angezeigt werden, aber du hast ja nur geschrieben, dass Tooltips angezeigt werden, wenn mit der Maus drübergehalten wird. Und DAS funktioniert. Vielen Dank für den Tipp! :-D Leider werden trotzdem keine #0's angezeigt. :cry: |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Ich denke, dass solcherlei Zeichen nur dann angezeigt werden, wenn sie mittendrin im String sind, nicht am Ende.
Grüße Dalai |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Im "String" ist die #0 drin, aber deine Variable (bzw. der Teil des Records), welche du anzeigen lässt,
ist ein PChar und der ist natürlich 0-terminiert, also endet hier die Auswertung somit bei/vor der ersten #0, unabhängig davon ob der Speicher, auf welchen dieser PChar zeigt, mehr Nullen enthält. Das hat dann natürlich nichts damit zu tun, dass die verwendete API diesen PChar-Zeiger als Liste auswertet. Es wäre natürlich praktisch, wenn es dafür einen eigenen Listen-PChar-Typen gäbe, wo dann auch der Debugger weiß, dass bei diesem Typen eine #0 enthalten sein kann und die Anzeige erst beim #0#0 endet. |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Danke für die Info! :)
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Auch als Dokumentation für den Entwickler, denn bei PChar bzw. LPCSTR usw. denkt doch jeder erstmal an "endet mit #0".
Gäbe es einen eigenen Typen, dann wüssten Entwickler und Debugger sofort, dass es hier bis #0#0 geht. (ohne die Dokumentation für diese spezielle Variable/Parameter zu kennen) Wie z.B. beim TDateTime, der ja eigentlich auch nur ein Double ist, den der Debugger aber "verständlicher" Darstellen kann. :zwinker: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:48 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-2025 by Thomas Breitkreuz