Hallo. Eine Windows-API Funktion verlangt als Argument ein LPCSTR. Also ein Zeiger auf const char. Dieser String soll ein doppelt-Null terminierter String sein. Intuitiv würde ich ja folgendes machen: const char Buf[]={"test\0\0"}; LPCSTR pBuf = Buf; //einsetzten in die WinAPI: meineWinApi(pBuf); //Prototype void meineWinApi( LPCSTR ); Meiner Meinung nach würde das aber nicht einen doppelt-Null terminierten String erzeugen, da die erste Null Sequenz "\0" den String terminiert und die zweite Null Sequenz ignoriert. Im Speicher würde also [t| e |s| t| 0] stehen. Falls meine Annahme richtig ist, wie kann man denn korrekt einen doppelt Null terminierten String erzeugen, wie sie die WinApi ja erwartet. Gruß Christian
Hab von Doppel-Nullen (außer bei James Bond) ja noch nie etwas gehört ... die Windows-Fuzzies machen immer komische Sachen. Aber in C bleibt Deine Doppel-Null am Ende schon erhalten. Deine Variable Buf zeigt auf einen Speicherbereich, der 6 Zeichen lang ist und an dessen Ende 2 Null-Bytes stehen. Die Variable pBuf zeigt dann auf denselben Speicherberich. Ich denke also, daß Du schon ganz korrekt einen Doppel-Null-terminierten String erzeugt hast.
Christian schrieb: > Eine Windows-API Funktion verlangt als Argument ein LPCSTR. > Also ein Zeiger auf const char. Dieser String soll ein doppelt-Null > terminierter String sein. nenn doch mal bitte die API funktion. Ich kann es noch gar nicht so recht glauben.
was willst du? von welcher API-Routine redest du? doppelt null-terminierte Strings werden meist da verlangt, wo man eine Liste von strings erwartet. Christian schrieb: > const char Buf[]={"test\0\0"}; > LPCSTR pBuf = Buf; Christian schrieb: > Meiner Meinung nach würde das aber nicht einen doppelt-Null terminierten > String erzeugen, komische Meinung > da die erste Null Sequenz "\0" den String terminiert > und die zweite Null Sequenz ignoriert. warum sollte er das tun? der Compiler macht genau das, was du ihm sagst. wenn du ihm ein Stringliteral gibst, erzeugt er genau so ein Array + ein zusätzliches '\0'. Dein Buff hat also sogar 3 '\0'en.
Wie kommst Du eigentlich auf Doppel-Null??? Da steht nur, daß es ein ganz stink normaler Null-terminierter const char * ist ... http://msdn.microsoft.com/en-us/library/cc230350.aspx
>nenn doch mal bitte die API funktion.
Hier:
SC_HANDLE WINAPI CreateService(
In SC_HANDLE hSCManager,
In LPCTSTR lpServiceName,
In_opt LPCTSTR lpDisplayName,
In DWORD dwDesiredAccess,
In DWORD dwServiceType,
In DWORD dwStartType,
In DWORD dwErrorControl,
In_opt LPCTSTR lpBinaryPathName,
In_opt LPCTSTR lpLoadOrderGroup,
Out_opt LPDWORD lpdwTagId,
In_opt LPCTSTR lpDependencies,
In_opt LPCTSTR lpServiceStartName,
In_opt LPCTSTR lpPassword
);
Betrifft das 3.letzte Argument lpDependencies.
MSDN sagt folgendes:
A pointer to a double null-terminated array of null-separated names of
services or load ordering groups that the system must start before this
service.
Gruß
Christian
Peter II schrieb: > nenn doch mal bitte die API funktion. Ich kann es noch gar nicht so > recht glauben. ich glaube zB bei den File-dialogen bei den Masken. da gibt man die einzelnen Optionen durch \0 getrennt an und schließt das ganze durch einen leeren string, also zwei \0
Christian schrieb: > A pointer to a double null-terminated array genau das meine Vlad Tepesch hier geht es nicht im einen String sondern um eine StringListe.
Christian schrieb: > MSDN sagt folgendes: > A pointer to a double null-terminated array of null-separated names of > services or load ordering groups that the system must start before this > service. Ich nehme an du meinst Parameter pDependencies genau das ganze muss dann so aussehen: "Abhängigkeit1\0Abhängigkeit2\0Abhängigkeit3\0\0"
Christian schrieb: > A pointer to a double null-terminated array of null-separated names of > services or load ordering groups that the system must start before this > service. Das sind mehrere im Speicher direkt hintereinanderliegende nullterminierte Strings, das Ende wird durch zwei aufeinanderfolgende Nullen gekennzeichnet. Also: Hallo\0Egon\0Berta\0foobar\0\0 Es ist also kein Array von Pointern auf Strings! So etwas kann man durch Kopieren der Teilstrings in ein ausreichend großes, vorher Nullinitialisiertes Array erreichen (denn auf die terminierende Doppel-Null dürfen beliebig viele weitere Nullen folgen ...).
ich finde das ganze übrigends recht clever. anstatt ein array aus char* und länge zu übergeben. Itererieren ist auch einfach
1 | const char* d0ta; |
2 | |
3 | for(; d0ta[0]; d0ta+=strlen(d0ta)+1 ) |
4 | {
|
5 | printf ("%s \n",d0ta); |
6 | }
|
Edit: hab das auch schon benutzt. besonders für Stringlisten als Rückgabewerte bietet sich das an. Die Funktion bekommt Speicher und eine max Länge und kann dann so viele strings zurückgeben wie platz ist.
Vlad Tepesch schrieb: > ich finde das ganze übrigends recht clever. > anstatt ein array aus char* und länge zu übergeben. geht auch ohne länge, wenn man festlegt das der letze Zeiger NULL sein muss. Dann kann man auch eine Liste von Zeigern übergeben.
Peter II schrieb: > geht auch ohne länge, wenn man festlegt das der letze Zeiger NULL sein > muss. Dann kann man auch eine Liste von Zeigern übergeben. stimmt natürlich, dennoch muss man auf der anderen Seite die Daten dann erst irgendwie zusammen kopieren. So bestimmt man die gesamt Länge und kopiert einen Block. Die Parameter bei denen ich dieses Format bisher gesehen habe, sind eher statisch und zur Kompilezeit bekannt (wie ebend jene Lsite mit Abhängigkeiten oder eben der Filterparameter der OPENFILENAME Struktur). Durch dieses Format entfällt das zusätzliche Array mit Pointern.
Also ist der Zweck, das man aus einen einzigen Array eine Liste aus Strings ereugt, anstand z.b. sowas: struct ArrayList { char arr1[]; char arr2[]; char arr3[]; } Man könnte doch aber dann auch die Adresse der struct übergeben, was genauso einfach ist. Oder? Gruß Christian
Am Ende muss nicht \0\0 stehen weil das " auch eine \0 anfügt. "a\0b\0c\0" reicht also.
Christian schrieb: > Also ist der Zweck, das man aus einen einzigen Array eine Liste aus > Strings > ereugt, anstand z.b. sowas: > > struct ArrayList > { > char arr1[]; > char arr2[]; > char arr3[]; > } das geht nicht und ist auch nicht sinnvoll, da die aufgerufene Funktion ja nicht weiß, wieviel strings du ihr geben willst. Alternative wäre ein Array, aus char*, also:
1 | const char* strList[4] = {//ein eintrag mehr, wegen null-pointer als Endemarke |
2 | "string 1", "string2", "string3" |
3 | };
|
wäre genauso einfach, aber bräuchte Speicher für 4 char* mehr und erfordert eine zusätzliche Dereferenzierung. Beide Varianten haben Vorteile und Nachteile.
Peter II schrieb: > geht auch ohne länge, wenn man festlegt das der letze Zeiger NULL sein > muss. Dann kann man auch eine Liste von Zeigern übergeben. Trotz allem hast du dann noch mindestens 2 Speicherbereiche, das Array und der Speicher in dem sie Strings selbst liegen. So kommt man mit einem Block aus. Man könnte natürlich erst das Array und dann die Werte hintereinander in einen Block schreiben, dann wäre der wahlfreie Zugriff über das Array einfacher, das Erzeugen aber komplexer. Immer die Frage was man will.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.