_tmain
nie istnieje w C ++. main
robi.
_tmain
jest rozszerzeniem Microsoft.
main
jest, zgodnie ze standardem C ++, punktem wejścia programu. Ma jeden z tych dwóch podpisów:
int main();
int main(int argc, char* argv[]);
Microsoft dodał wmain, który zastępuje drugi podpis tym:
int wmain(int argc, wchar_t* argv[]);
Następnie, aby ułatwić przełączanie między Unicode (UTF-16) a ich wielobajtowym zestawem znaków, zdefiniowali, _tmain
który, jeśli włączony jest Unicode, jest kompilowany jako wmain
, a inaczej jako main
.
Jeśli chodzi o drugą część twojego pytania, pierwszą częścią układanki jest to, że twoja główna funkcja jest zła. wmain
powinien wziąć wchar_t
argument, nie char
. Ponieważ kompilator nie wymusza tego dla main
funkcji, otrzymujesz program, w którym tablica wchar_t
ciągów znaków jest przekazywana do main
funkcji, która interpretuje je jako char
ciągi znaków.
Teraz, w UTF-16, zestaw znaków używanych przez Windows, gdy włączony jest Unicode, wszystkie znaki ASCII są reprezentowane jako para bajtów, \0
po których następuje wartość ASCII.
A ponieważ procesor x86 jest little-endian, kolejność tych bajtów jest zamieniana, tak że najpierw pojawia się wartość ASCII, a następnie bajt zerowy.
A w ciągu znaków char, jak zwykle jest zakończony? Tak, bajt zerowy. Więc twój program widzi kilka ciągów znaków, każdy o długości jednego bajtu.
Ogólnie rzecz biorąc, masz trzy opcje podczas programowania w systemie Windows:
- Jawnie użyj Unicode (wywołaj wmain, a dla każdej funkcji Windows API, która pobiera argumenty związane z char, wywołaj
-W
wersję funkcji. Zamiast CreateWindow, wywołaj CreateWindowW). I zamiast używać char
use wchar_t
, i tak dalej
- Jawnie wyłącz Unicode. Wywołaj main, CreateWindowA i użyj
char
dla łańcuchów.
- Pozwól na oba. (wywołaj _tmain i CreateWindow, które rozstrzygają się na main / _tmain i CreateWindowA / CreateWindowW) i użyj TCHAR zamiast char / wchar_t.
To samo dotyczy typów ciągów zdefiniowanych przez windows.h: LPCTSTR rozwiązuje albo LPCSTR albo LPCWSTR, a dla każdego innego typu, który zawiera char lub wchar_t, zawsze istnieje wersja -T-, której można użyć zamiast tego.
Pamiętaj, że wszystko to jest specyficzne dla Microsoft. TCHAR nie jest standardowym typem C ++, jest makrem zdefiniowanym w windows.h. wmain i _tmain są również zdefiniowane tylko przez Microsoft.
UNICODE
. I kilka innych poprawek dla C ++ itp., Przed włączeniem<windows.h>
. Następnie użyj funkcji Unicode takich jakCreateWindow
(na ogół bezW
potrzeby na końcu)._tmain to makro, które zmienia się w zależności od tego, czy kompilujesz z Unicode czy ASCII. Jest to rozszerzenie Microsoft i nie ma gwarancji, że będzie działać na innych kompilatorach.
Prawidłowa deklaracja to
Jeśli zdefiniowane jest makro UNICODE, rozwija się ono do
W przeciwnym razie rozwija się do
Twoja definicja obejmuje trochę każdego z nich i (jeśli masz zdefiniowany UNICODE) rozwinie się do
co jest po prostu błędne.
std :: cout działa ze znakami ASCII. Potrzebujesz std :: wcout, jeśli używasz szerokich znaków.
spróbuj czegoś takiego
Możesz też z góry zdecydować, czy użyć szerokich, czy wąskich znaków. :-)
Zaktualizowano 12 listopada 2013:
Zmieniono tradycyjny „TCHAR” na „_TCHAR”, który wydaje się być najnowszą modą. Oba działają dobrze.
Zakończ aktualizację
źródło
Konwencja _T służy do wskazania, że program powinien używać zestawu znaków zdefiniowanego dla aplikacji (Unicode, ASCII, MBCS itp.). Możesz otoczyć swoje ciągi _T (), aby były przechowywane w odpowiednim formacie.
źródło
char
s wcześniej. Jeśli aplikacja używa bezpośrednio, oznaczawchar_t
to, że jest to kod Unicode.Ok, wydaje się, że odpowiedź na to pytanie jest dość dobra, przeciążenie UNICODE powinno zająć szeroką tablicę znaków jako drugi parametr. Więc jeśli parametr wiersza poleceń jest
"Hello"
taki, że prawdopodobnie skończyłby się tak,"H\0e\0l\0l\0o\0\0\0"
a twój program wydrukowałby tylko'H'
zanim zobaczy, co uważa za terminator zerowy.Więc teraz możesz się zastanawiać, dlaczego nawet się kompiluje i łączy.
Kompiluje się, ponieważ można zdefiniować przeciążenie funkcji.
Łączenie jest nieco bardziej złożonym problemem. W C nie ma dekorowanych informacji o symbolach, więc znajduje funkcję o nazwie main. Argc i argv są zawsze dostępne jako parametry stosu wywołań na wszelki wypadek, nawet jeśli twoja funkcja jest zdefiniowana z tą sygnaturą, nawet jeśli twoja funkcja je zignoruje.
Mimo że C ++ ma udekorowane symbole, prawie na pewno używa C-linkage dla main, a nie sprytnego linkera, który szuka każdego z nich z kolei. Więc znalazł twojego wmaina i umieścił parametry na stosie wywołań na wypadek, gdyby była to
int wmain(int, wchar_t*[])
wersja.źródło
Przy odrobinie wysiłku, aby to zrobić, to zadziałało z dowolną listą obiektów.
źródło