Wann nimmt man eigentlich was?
Jedesmal wenn ich Code ansehe finde ich mal einen
#ifdef _UNICODE
dann mal wieder einen
#ifdef UNICODE
Wann eigentlich was?
Die Frage wurde schon oft beantwortet (siehe The Old New Thing : TEXT vs. _TEXT vs. _T, and UNICODE vs. _UNICODE).
In Kurzform:
UNICODE wird in den Windows Header-Dateien verwendet.
_UNICODE in der C-Runtime (CRT).
Interessanterweise gibt es nur den Define _MBCS aber nicht den Define MBCS. Anhand der Namensgebung kann man sehen, dass _MBCS aus/für die CRT nur Einfluss hat. Die Windows API sagt einfach, wenn nicht Unicode dann ist es MBCS!
Daraus ergeben sich einige interessante Abhängigkeiten:
_T ist abhängig vom Define _UNICODE genauso wie _TEXT (also der CRT)
TEXT ist wiederum abhängig vom Define UNICODE.
Jetzt wird es aber ganz lustig:
Die Datei tchar.h gehört zur CRT. Und TCHAR ist eigentlich kein Define aus tchar.h und der CRT. Dort wird nämlich eigentlich _TCHAR definiert und sollte TCHAR schon definiert sein (durch die windows.h), dann wird TCHAR nicht mehr umdefiniert.
Ist also nur UNICODE definiert und nicht _UNICODE, dann muss der folgende Code einen Compiler Fehler auslösen, wenn windows.h vor der tchar.h inkludiert wird. Erwartungsgemäß meldet der folgende Code einen Compiler-Fehler, obwohl dieser perfekt und korrekt aussieht:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
const TCHAR szText[] = „“;
// Must fail if UNICODE is defined and not _UNICODE, and windows.h included first
_tcslen(szText);
return 0;
}
In VC6 gab es noch keine Projekteinstellung für Unicode. Man musste also beide Defines setzen, als Präprozessor Definition. Andernfalls hatte man eine lustige Code Mischung und lief schnell mal in ein Problem wie oben.
Der Schalter in VC-2005 und VC-2003 für
- „Use Unicode Character Set“ setzt beide Defines _UNICODE und UNICODE
- „Use Multi-Byte Character Set“ setzt nur _MBCS.
- „Not set“ setzt Erwartungsgemäß keinen der Defines und man kann das obige Beispiel und den Fehler ausprobieren.
Projektintern verwende ich grundsätzlich immer intern nur den define UNICODE um zu prüfen welche Art von Projekt hier läuft. Und ich achte darauf, dass die windows.h bzw. die afxwin.h Datei immer als erstes inkludiert werden. Dann ist TCHAR entsprechend konform für die Windows API gesetzt. Die CRT ist für mich meistens nur Beiwerk und ich vermeide Ihre Verwendung eigentlich wo ich kann.
An kritischen Stellen baue ich auch gerne den folgenden Test ein um ganz auf Nummer sicher zu gehen:
#if defined(UNICODE) ^ defined(_UNICODE)
#error Inconsitent UNICODE and _UNICODE definition
#endif
Mit dem XOR-Operator wird hier ein Fehler ausgelöst wenn nur einer der beiden Defines gesetzt ist.
Siehe auch die MSDN INFO: UNICODE and _UNICODE Needed to Compile for Unicode