_tmain
existiert nicht in C ++. main
tut.
_tmain
ist eine Microsoft-Erweiterung.
main
ist nach dem C ++ - Standard der Einstiegspunkt des Programms. Es hat eine dieser beiden Signaturen:
int main();
int main(int argc, char* argv[]);
Microsoft hat ein wmain hinzugefügt, das die zweite Signatur durch Folgendes ersetzt:
int wmain(int argc, wchar_t* argv[]);
Um den Wechsel zwischen Unicode (UTF-16) und ihrem Multibyte-Zeichensatz zu vereinfachen, haben sie definiert, _tmain
welcher, wenn Unicode aktiviert ist, als wmain
und ansonsten als kompiliert wird main
.
Was den zweiten Teil Ihrer Frage betrifft, so ist der erste Teil des Puzzles, dass Ihre Hauptfunktion falsch ist. wmain
sollte ein wchar_t
Argument nehmen, nicht char
. Da der Compiler dies für die main
Funktion nicht erzwingt , erhalten Sie ein Programm, in dem ein Array von wchar_t
Zeichenfolgen an die main
Funktion übergeben wird, die sie als char
Zeichenfolgen interpretiert .
In UTF-16, dem Zeichensatz, der von Windows verwendet wird, wenn Unicode aktiviert ist, werden alle ASCII-Zeichen als Bytepaar \0
gefolgt vom ASCII-Wert dargestellt.
Und da die x86-CPU Little-Endian ist, wird die Reihenfolge dieser Bytes vertauscht, sodass der ASCII-Wert zuerst kommt, gefolgt von einem Null-Byte.
Und wie wird die Zeichenfolge in einer Zeichenfolge normalerweise beendet? Ja, um ein Null-Byte. Ihr Programm sieht also eine Reihe von Zeichenfolgen, die jeweils ein Byte lang sind.
Im Allgemeinen haben Sie bei der Windows-Programmierung drei Möglichkeiten:
- Verwenden Sie explizit Unicode (rufen Sie wmain auf und rufen Sie für jede Windows-API-Funktion, die char-bezogene Argumente
-W
akzeptiert, die Version der Funktion auf. Rufen Sie anstelle von CreateWindow CreateWindowW auf). Und anstatt Verwendung zu char
verwenden wchar_t
, und so weiter
- Deaktivieren Sie Unicode explizit. Rufen Sie main und CreateWindowA auf und verwenden Sie sie
char
für Zeichenfolgen.
- Erlaube beides. (Rufen Sie _tmain und CreateWindow auf, die in main / _tmain und CreateWindowA / CreateWindowW aufgelöst werden.) Verwenden Sie TCHAR anstelle von char / wchar_t.
Gleiches gilt für die von windows.h definierten Zeichenfolgentypen: LPCTSTR wird entweder in LPCSTR oder LPCWSTR aufgelöst, und für jeden anderen Typ, der char oder wchar_t enthält, ist immer eine -T-Version vorhanden, die stattdessen verwendet werden kann.
Beachten Sie, dass dies alles Microsoft-spezifisch ist. TCHAR ist kein Standard-C ++ - Typ, sondern ein in windows.h definiertes Makro. wmain und _tmain werden ebenfalls nur von Microsoft definiert.
UNICODE
. Und einige andere Anpassungen für C ++ usw., bevor sie aufgenommen werden<windows.h>
. Verwenden Sie dann die Unicode-Funktionen wieCreateWindow
(im Allgemeinen ohneW
am Ende benötigt)._tmain ist ein Makro, das neu definiert wird, je nachdem, ob Sie mit Unicode oder ASCII kompilieren oder nicht. Es ist eine Microsoft-Erweiterung und funktioniert garantiert nicht mit anderen Compilern.
Die richtige Erklärung ist
Wenn das Makro UNICODE definiert ist, wird das auf erweitert
Ansonsten erweitert es sich auf
Ihre Definition gilt für jeweils ein bisschen und wird (wenn Sie UNICODE definiert haben) auf erweitert
Das ist einfach falsch.
std :: cout arbeitet mit ASCII-Zeichen. Sie benötigen std :: wcout, wenn Sie breite Zeichen verwenden.
versuche so etwas
Oder Sie können einfach im Voraus entscheiden, ob Sie breite oder schmale Zeichen verwenden möchten. :-)
Aktualisiert am 12. November 2013:
Das traditionelle "TCHAR" wurde in "_TCHAR" geändert, was die neueste Mode zu sein scheint. Beide funktionieren gut.
Update beenden
quelle
Die _T-Konvention gibt an, dass das Programm den für die Anwendung definierten Zeichensatz verwenden soll (Unicode, ASCII, MBCS usw.). Sie können Ihre Zeichenfolgen mit _T () umgeben, damit sie im richtigen Format gespeichert werden.
quelle
char
s vor. Wenn Ihre Anwendung direkt verwendetwchar_t
dann Ihre Anwendung ist Unicode.Ok, die Frage scheint ziemlich gut beantwortet worden zu sein. Die UNICODE-Überladung sollte ein breites Zeichenarray als zweiten Parameter verwenden. Wenn also der Befehlszeilenparameter lautet
"Hello"
, würde dies wahrscheinlich als enden"H\0e\0l\0l\0o\0\0\0"
und Ihr Programm würde nur das drucken,'H'
bevor es sieht, was es für einen Nullterminator hält.Jetzt fragen Sie sich vielleicht, warum es überhaupt kompiliert und verlinkt.
Nun, es wird kompiliert, weil Sie eine Überladung einer Funktion definieren dürfen.
Das Verknüpfen ist ein etwas komplexeres Thema. In C gibt es keine dekorierten Symbolinformationen, daher wird nur eine Funktion namens main gefunden. Argc und argv sind wahrscheinlich immer als Call-Stack-Parameter vorhanden, nur für den Fall, dass Ihre Funktion mit dieser Signatur definiert ist, auch wenn Ihre Funktion sie ignoriert.
Obwohl C ++ verzierte Symbole hat, verwendet es mit ziemlicher Sicherheit die C-Verknüpfung für main und nicht einen cleveren Linker, der nacheinander nach jedem sucht. Also hat es Ihren wmain gefunden und die Parameter auf den Call-Stack gelegt, falls es sich um die
int wmain(int, wchar_t*[])
Version handelt.quelle
Mit ein wenig Aufwand, dies zu templatisieren, würde es mit jeder Liste von Objekten funktionieren.
quelle