Frage zu Datentyp Konvertierung
-
Hallo, ich wollte gerade einen Quelltext von mir mit einem anderen Compiler übersetzten aber da gab es einen Fehler bei der Datentyp Konvertierung.
Funktion:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724844(v=vs.85).aspx LONG WINAPI RegCreateKeyEx( _In_ HKEY hKey, _In_ LPCTSTR lpSubKey, _Reserved_ DWORD Reserved, _In_opt_ LPTSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition );
Bei meinem Codegear Compiler führe ich die Funktion so aus:
LPCTSTR ValueName = "TestKey"; const BYTE *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ,KeyData, strlen(KeyData)+1);
Bei Codeblocks muss ich es aber so machen:
LPCTSTR ValueName = "TestKey"; char *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ, (BYTE*)&KeyData, strlen(KeyData)+1);
Weiß jemand was der Compiler hier macht? (BYTE*)&KeyData
Ich denke mal er übergibt die Adresse der Variable KeyData an die Funktion RegSetValueEx. Aber wenn dem so wäre/ist dann müsste ich doch auch schreiben können:LPCTSTR ValueName = "TestKey"; char *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ,&KeyData, strlen(KeyData)+1);
Ich versteh nicht wieso der Codeblocks Compiler da noch das (BYTE*) haben will.
-
convert_ schrieb:
Weiß jemand was der Compiler hier macht? (BYTE*)&KeyData
Er weint innerlich, weil du ihm befiehlst, still zu sein, obwohl er genau sieht, dass es falsch ist.
Du übergibst da die Adresse des Zeigers.
-
Du meinst die Funktion: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724923(v=vs.85).aspx
Dein erstes Beispiel ist korrekt: Die Funktion erwartet einen Zeiger auf const BYTE (BYTE ist Typedef zu unsigned char), du gibst ihr einen. Alles gut.
Dein zweites Beispiel ist ohne Cast nicht korrekt: Die Funktion erwartet immer noch einen Zeiger auf const BYTE, du gibst ihr aber die Adresse eines Zeigers auf char. Der Typ einer Adresse eines Zeigers auf char ist char**. char** ist ungleich const BYTE*. Der Cast sagt hier soviel "Klappe, Compiler, ich weiß, was ich tue, mach das so wie ich das will". Compiler machts. Programm crasht. Compiler denkt sich "Ich habs dir ja gesagt". Fazit: Du weißt nicht, was du tust, caste nicht. Insbesondere keine C-Style Casts.Nachtrag: Selbst wenn du nicht die Adresse des Zeigers übergeben hättest, char* ist immer noch etwas anderes als unsigned char*. Mach es also so wie im ersten Beispiel.
Nachtrag 2: An deinem zweiten Beispiel ist noch etwas anderes nicht schön: Erstelle keinen Zeiger auf char von einem Stringliteral, es muss ein Zeiger auf const char sein, da du das Literal ja nicht ändern kannst. Ersteres ist nur aus historischen Gründen erlaubt. Aktiviere also Warnungen deines Compilers, der warnt da nämlich vor!
Editierter Nachtrag 3: Wenn du schon die T-Str-Variante nimmst, nimm auch das TEXT-Makro, sonst haste nämlich Compilerfehler, sobald du Unicode aktivierst.
-
convert_ schrieb:
Bei meinem Codegear Compiler führe ich die Funktion so aus:
LPCTSTR ValueName = "TestKey"; const BYTE *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ,KeyData, strlen(KeyData)+1);
Bei Codeblocks muss ich es aber so machen:
LPCTSTR ValueName = "TestKey"; char *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ, (BYTE*)&KeyData, strlen(KeyData)+1);
Weiß jemand was der Compiler hier macht? (BYTE*)&KeyData
Ich denke mal er übergibt die Adresse der Variable KeyData an die Funktion RegSetValueEx. Aber wenn dem so wäre/ist dann müsste ich doch auch schreiben können:LPCTSTR ValueName = "TestKey"; char *KeyData = "test"; RegSetValueEx(phkResult,ValueName,0,REG_SZ,&KeyData, strlen(KeyData)+1);
Ich versteh nicht wieso der Codeblocks Compiler da noch das (BYTE*) haben will.
Warum hat den KeyData plötzlich einen anderen Typ? Beide deiner (Codeblocks-)Varianten sind im Übrigen falsch.
-
Pointer werden soweit ich weiss nicht implizit konvertiert, auch wenn der eine Typ (
BYTE
) lediglich ein typedef des anderen ist (char
).Die Funktion erwartet einen
const BYTE*
als Argument, daher wird derchar*
den du wahrscheinlich zuerst versucht hast zu übergeben nicht akzeptiert. Wahrscheinlich hätte das Codegear ebenfalls beanstandet, dort hatKeyData
allerdings bereits den Typen, den die Funktion erwartet.Dein Code enthält allerdings noch einen gravierenden Fehler:
&KeyData
ist nicht vom Typchar*
sondern vom Typchar**
(Zeiger auf einen Zeiger auf char). Was du also an die Funktion übergibst ist nicht ein Zeiger auf die Zeichenfolge, sondern ein Zeiger auf die (de facto) Speicheradresse an der die Adresse der Zeichenfolge gespeichert ist. Korrekt müsste das Argument so aussehen:
(BYTE*) KeyData
oder noch besser (C++-Style, ist schließlich ein C++-Forum):
reinterpret_cast<BYTE*>(KeyData)
Gruss,
Finnegan
-
Finnegan schrieb:
Pointer werden soweit ich weiss nicht implizit konvertiert, auch wenn der eine Typ (
BYTE
) lediglich ein typedef des anderen ist (char
).Typedefs sind keine eigenen Typen, nur Namen für bereits existierende Typen. Die Zeiger werden dabei tatsächlich nicht konvertiert, aber nur weil es nichts zu konvertieren gibt.
WobeiBYTE
typischerweise ein typedef aufunsigned char
ist, und das ist nicht das selbe wiechar
odersigned char
.Finnegan schrieb:
Die Funktion erwartet einen
const BYTE*
als Argument, daher wird derchar*
den du wahrscheinlich zuerst versucht hast zu übergeben nicht akzeptiert.Das ist vermutlich richtig, da wie gerade erwähnt,
BYTE
typischerweise ein typedef aufunsigned char
ist, und einchar
-Zeiger ist natürlich nicht implizit in einenunsigned char
-Zeiger konvertierbar.