2013-07-19 7 views
11

Pracuję z istniejącą aplikacją i próbuję ustalić różnicę między aplikacjami skompilowanymi z Multi byte character set i Not Set pod opcją Character Set.Zestawy znaków programu Visual Studio "Nie ustawiono" zamiast "Zestaw znaków wielobajtowych"

Rozumiem, że kompilacja z Multi byte character set definiuje _MBCS która pozwala wielu bajtowych stron kodowych zestawu znaków do wykorzystania, a przy użyciu Not set nie definiuje _MBCS, w takim przypadku możliwe jest tylko jeden bajt stron kodowych zestawu znaków.

W przypadku, Not Set jest używany, jestem przy założeniu, że wtedy możemy użyć tylko jeden bajt znalezione na tej stronie zestawu znaków stron kodowych: http://msdn.microsoft.com/en-gb/goglobal/bb964654.aspx

Dlatego mam rację sądząc, że jest to Not Set zastosowany, aplikacja nie będzie w stanie kodować i pisać lub czytać języków dalekowschodnich, ponieważ są one zdefiniowane na stronach kodowych znaków dwubajtowych (i oczywiście w Unicode)?

Kontynuacja tej czynności, jeśli zdefiniowano zestaw Multi byte character, czy dostępne są strony kodowe pojedynczych i wielobajtowych zestawów znaków czy tylko wielobajtowe strony kodowe zestawu znaków? Zgaduję, że musi to być zarówno dla języków europejskich, które mają być obsługiwane.

Dzięki,

Andy

Dalsze Reading

Odpowiedzi na tych stronach nie odpowiedział na moje pytanie, ale pomógł w moim rozumieniu: About the "Character set" option in visual studio 2010

Badań

Tak, podobnie jak prace badawcze ...Z moim narodowe ustawiony japońskim

Wpływ na twardych zakodowanych ciągów

char *foo = "Jap text: テスト"; 
wchar_t *bar = L"Jap text: テスト"; 

kompilacji z Unicode

* xxx = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
* słupek = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16 or UCS-2

Kompilacja z Multi byte character set

* xxx = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
* bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 30 B9 30 C6 C8 30 == UTF-16 or UCS-2

Kompilacja z Not Set

* foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (Code page 932)
* słupek = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 B9 30 C8 30 == UTF-16 or UCS-2

Wniosek: kodowanie znaków nie ma żadnego wpływu na twardych zakodowanych ciągów. Chociaż definiowanie znaków jak powyżej wydaje się używać strony kodowej zdefiniowanej w języku Locale, a wchar_t wydaje się używać UCS-2 lub UTF-16.

Korzystanie zakodowanych sznurki w wersji/A Win32 API

Tak, stosując następujący kod:

char *foo = "C:\\Temp\\テスト\\テa.txt"; 
wchar_t *bar = L"C:\\Temp\\テスト\\テw.txt"; 

CreateFileA(bar, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
CreateFileW(foo, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

kompilacji z Unicode

Wynik: Oba pliki są tworzone

Kompilacja z Multi byte character set

Wynik: Oba pliki są tworzone

kompilacji z Not set

Wynik: Oba pliki są tworzone

Wniosek: Zarówno wersja API A i W oczekiwać tego samego kodowania niezależnie od wybrany zestaw znaków. Z tego, być może możemy założyć, że wszystkie opcje Character Set jest przełączanie między wersją API. Tak więc wersja A zawsze oczekuje ciągów znaków w kodowaniu bieżącej strony kodowej, a wersja W zawsze oczekuje od UTF-16 lub UCS-2.

pliki otwarcia wykorzystujące W i Win32 API

Więc stosując następujący kod:

char filea[MAX_PATH] = {0}; 
OPENFILENAMEA ofna = {0}; 
ofna.lStructSize = sizeof (ofna); 
ofna.hwndOwner = NULL ; 
ofna.lpstrFile = filea ; 
ofna.nMaxFile = MAX_PATH; 
ofna.lpstrFilter = "All\0*.*\0Text\0*.TXT\0"; 
ofna.nFilterIndex =1; 
ofna.lpstrFileTitle = NULL ; 
ofna.nMaxFileTitle = 0 ; 
ofna.lpstrInitialDir=NULL ; 
ofna.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ; 

wchar_t filew[MAX_PATH] = {0}; 
OPENFILENAMEW ofnw = {0}; 
ofnw.lStructSize = sizeof (ofnw); 
ofnw.hwndOwner = NULL ; 
ofnw.lpstrFile = filew ; 
ofnw.nMaxFile = MAX_PATH; 
ofnw.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0"; 
ofnw.nFilterIndex =1; 
ofnw.lpstrFileTitle = NULL; 
ofnw.nMaxFileTitle = 0 ; 
ofnw.lpstrInitialDir=NULL ; 
ofnw.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ; 

GetOpenFileNameA(&ofna); 
GetOpenFileNameW(&ofnw); 

i wybierając albo:

  • C: \ Temp \ テ ス ト \ テ openw .txt
  • C: \ Temp \ テ ス ト \ テ openw.txt

Wydajność:

z wkompilowaną Unicode

* filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 = = Shift-Jis (Code page 932) * filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 or UCS-2

z wkompilowaną Multi byte character set

* filea = 43 5c 54 65 3a 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 2e 6e 61 74 78 74 == Shift-Jis (Code page 932)
* filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 or UCS-2

Gdy kompilowany z Not Set

* filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis (Code page 932)
* filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 30 B9 30 C6 C8 30 5c 00 C6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 or UCS-2

Wniosek: Ponownie , ustawienie Character Set nie ma wpływu na zachowanie Win32 API. Wersja A zawsze wydaje się zwracać ciąg znaków z kodowaniem aktywnej strony kodowej, a zawsze zwraca się kodowanie UTF-16 lub UCS-2. Mogę zobaczyć, jak wyjaśniono to w tej wspaniałej odpowiedzi: https://stackoverflow.com/a/3299860/187100.

Ostateczny Conculsion

Hans wydaje się być poprawne, gdy mówi, że określenie tak naprawdę nie mają żadnej magii do niego, poza zmianą API Win32, aby użyć W lub A. Dlatego tak naprawdę nie widzę żadnej różnicy między Not Set i Multi byte character set.

Odpowiedz

6

Nie, to tak naprawdę nie działa. Jedyne, co się dzieje, to to, że makro zostaje zdefiniowane, w przeciwnym razie nie ma magicznego wpływu na kompilator. Bardzo trudno jest napisać kod, który używa #ifdef _MBCS do testowania tego makra.

Prawie zawsze należy pozostawić funkcję pomocnika, aby dokonać konwersji. Podobnie jak WideCharToMultiByte(), OLE2A() lub wctombs(). Które są funkcjami konwersji, które zawsze uwzględniają kodowanie wielobajtowe, kierując się stroną kodową. _MBCS jest historycznym wypadkiem, mającym znaczenie tylko 25+ lat temu, kiedy kodowanie wielobajtowe nie było jeszcze powszechne. Podobnie jak używanie kodowania nie będącego Unicode, jest również historycznym artefaktem.

+0

Więc jeśli dobrze rozumiem, jeśli zdefiniuję sztywno zakodowany ciąg, powiedz char * foo = "テ ス ト". W jaki sposób ciąg wskazany przez foo nie jest zdefiniowany przez ustawienie zestawu znaków? Może kodowanie pliku kodu zawierającego tę linię? (Próbuję przetestować te teorie w tej chwili) – Andy

+0

Zmusi to twój edytor tekstu do wyboru odpowiedniego kodowania dla pliku kodu źródłowego. Sam w sobie źródło wypadków. Jeśli wybrał kodowanie Unicode, utf-8 jest powszechny, możesz zmusić twój kompilator do nadęcia się z nim. C4566 na mojej maszynie.Zawsze myśl o pisaniu tego w ten sposób, jeśli mieszkasz w Japonii i nie planuj przeprowadzki w najbliższym czasie. –

+0

OK, więc wygląda na to, że rozumiem to teraz trochę lepiej. Definicje tak naprawdę nie robią zbyt wiele, strona kodowa jest ustawiona na komputerze, niezależnie od tego, jak aplikacja jest kompilowana, i definiuje po prostu zmianę interfejsów API Win32 i na podstawie tego, czy jest to W czy A, to pewnie zwróciłaby kod strony (wielobajtowy lub jednobajtowy zestaw znaków) zakodował materiał (A) lub UTF-16 (W)? – Andy

0

W reference stwierdza się, że:

Z definicji, zestaw znaków ASCII jest podzbiorem wszystkich zestawów wielobajtowych znaków. W wielu zestawach znaków wielobajtowych każdy znak w zakresie 0x00 - 0x7F jest identyczny z charakterem, który ma taką samą wartość w zestawie znaków ASCII. Na przykład w obu łańcuchach znaków ASCII i MBCS 01 bajtów 1-bajtowy znak NULL ("\ 0") ma wartość 0x00 i wskazuje kończący znak null.

Jak można się domyślić, poprzez włączenie funkcji _MBCS Visual Studio obsługuje także pojedynczy zestaw znaków ASCII.

W drugim reference, zestaw pojedynczy znak zdaje się być obsługiwane nawet jeśli pozwalają _MBCS:

MBC/przenośność Unicode: Korzystanie z pliku nagłówka Tchar.h, można zbudować pojedynczy bajt , MBCS i Unicode z tych samych źródeł. Tchar.h definiuje makra z prefiksem _tcs, które mapują do funkcji str, _mbs lub wcs, stosownie do potrzeb. Aby zbudować MBCS, zdefiniuj symbol _MBCS. Aby zbudować Unicode, zdefiniuj symbol _UNICODE. Domyślnie _MBCS to zdefiniowany dla aplikacji MFC. Aby uzyskać więcej informacji, zobacz Generic-Text Mapowania w Tchar.h.

+0

Ale nie używając '_MBCS', nie są to interfejsy API używające strony kodowej zestawu znaków jednobajtowych w oparciu o ustawienia narodowe, takie jak te zdefiniowane pod adresem: http://msdn.microsoft.com/en-gb/goglobal/ bb964654.aspx? Więc każdy z nich zaczyna się od zakresu ASCII, ale oni także definiują inne znaki obce. – Andy

+0

@Andy, Tak, ASCII to 7-bitowy zestaw znaków ze 128 znakami, podczas gdy jednobajtowe (8-bitowe) kodowanie lokalne może kodować 256 znaków. –

+0

tak, więc pytania pozostają nadal, jeśli zdefiniowano MBCS, to wykluczone są strony kodowe znaków jednobajtowych (a więc tajne znaki)? I jeśli kompiluję bez MBSC, domyślam się, że aplikacja nie byłaby w stanie obsłużyć znaków dalekowschodnich, ponieważ ogranicza się do jednobajtowych stron kodowych zestawu znaków> – Andy