2008-12-01 21 views
44

Jakie jest standardowe kodowanie kodu źródłowego C++? Czy standard C++ mówi coś o tym? Czy mogę napisać źródło C++ w Unicode?Korzystanie z Unicode w C++ kod źródłowy

Na przykład, czy mogę używać znaków spoza ASCII, takich jak chińskie znaki w komentarzach? Jeśli tak, czy dozwolony jest pełny kod Unicode lub tylko podzbiór kodu Unicode? (np. ta 16-bitowa pierwsza strona lub jakkolwiek się nazywa.)

Co więcej, czy mogę używać Unicode do ciągów? Na przykład:

Wstring str=L"Strange chars: â Țđ ě €€"; 
+0

* RE: "cokolwiek to się nazywa": * [Z Wikipedii] (https://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane): Pierwszy samolot, ** samolot 0 **, the ** Basic Multilingual Plane (BMP) ** zawiera znaki dla prawie wszystkich współczesnych języków i dużą liczbę symboli. Podstawowym celem BMP jest wspieranie ujednolicenia wcześniejszych zestawów znaków oraz znaków do pisania. Większość przypisanych punktów kodowych w BMP służy do kodowania znaków ** chińskich **, ** japońskich ** i ** koreańskich (CJK) **. – DavidRR

Odpowiedz

33

Kodowanie w C++ jest dość skomplikowane. Oto moje zrozumienie tego.

Każda implementacja musi obsługiwać znaki z podstawowego zestawu znaków źródłowych :. Obejmują one wspólne znaki wymienione w §2.2/1 (§2.3/1 w C++ 11). Wszystkie te znaki powinny pasować do jednego: char. Ponadto implementacje muszą obsługiwać sposób nazywania innych znaków przy użyciu metody o nazwie universal-character-names i wyglądać jak \uffff lub \Uffffffff i mogą być używane do odwoływania się do znaków Unicode. Podzbiór z nich można wykorzystywać w identyfikatorach (wymienionych w załączniku E).

To wszystko jest miłe, ale odwzorowanie od znaków w pliku, do znaków źródłowych (używanych w czasie kompilacji) to zdefiniowana implementacja. To stanowi używane kodowanie. Oto co mówi dosłownie (C++ 98 wersja):

znaków pliku źródłowego fizyczne są odwzorowany, w realizacji zdefiniowanej sposób na zasadowy charakter źródło zestawu (wprowadzenie znaków nowej linii dla wskaźników końca linii), jeśli konieczne jest . Sekwencje Trigraph (2.3) zastępuje się odpowiednimi jednobarwnymi wewnętrznymi reprezentacjami . Każdy plik źródłowy o numerze , który nie znajduje się w źródłowym źródle, został zmieniony na uniwersalny znak, który jest oznaczany przez des- .(Implementacja może używać kodowania wewnętrznego , tak długo, jak rzeczywiste dłuższy charakter napotkanego w pliku źródłowego, a tym samym rozszerzona charakter wyrażony w pliku źródłowym jako uniwersalny-znakowe nazwy (tj pomocą \ uXXXX notacja), są traktowane równoważnie .)

Dla gcc, można go zmienić za pomocą opcji -finput-charset=charset. Dodatkowo można zmienić znak wykonawczy używany do reprezentowania wartości w czasie wykonywania. Odpowiednią opcją jest -fexec-charset=charset dla char (domyślnie jest to utf-8) i -fwide-exec-charset=charset (domyślnie jest to utf-16 lub utf-32 w zależności od rozmiaru wchar_t).

9

Standard C++ nie mówi nic o kodowaniu plików kodu źródłowego, o ile wiem.

Zwykłe kodowanie jest (lub było kiedyś) siedmiobitowym ASCII - niektóre kompilatory (na przykład Borlanda) byłyby sprzeczne ze znakami ASCII, które używały high-bit. Nie ma technicznych powodów, że znaki Unicode nie mogą być użyte, jeśli twój kompilator i edytor je zaakceptują - większość nowoczesnych narzędzi opartych na Linuksie i wiele lepszych edytorów opartych na systemie Windows, bez problemu obsługuje kodowanie UTF-8, chociaż ja nie jestem pewien, że kompilator Microsoftu będzie.

EDIT: To wygląda jak kompilatory Microsoft zaakceptuje Unicode zakodowane pliki, ale czasami produkują błędy na 8-bitowym ASCII też:

warning C4819: The file contains a character that cannot be represented 
in the current code page (932). Save the file in Unicode format to prevent 
data loss. 
+0

To w pewien sposób. Nie sądzę, aby wyraźnie zapobiegał lub dopuszczał unikod, ale jest to minimalny dopuszczalny zestaw znaków: http://www.csci.csusb.edu/dick/c++dd/cd2/lex.html#lex.charset –

+0

Od wersji C++ Builder2007 kompilator Borland/Codegear obsługuje pliki źródłowe Unicode: tj. Literały znaków Unicode, komentarze w unicode. IDe trochę się z nimi zmaga, ale kompilator jest szczęśliwy! – Roddy

+0

To, o czym wspomniałem, pochodziło z Borland sprzed mniej więcej dwudziestu lat (ostatnio próbowałem umieszczać znak o wysokiej ASCII w pliku z kodem źródłowym). :-) Nie używałem kompilatora Borlanda w ciągu około dziesięciu lat. –

3

do kodowania w ciągach myślę, że są przeznaczone do używania \ u notacja, np:

std::wstring str = L"\u20AC"; // Euro character 
0

AFAIK To nie jest znormalizowana, jak można umieścić dowolny rodzaj znaków szerokich łańcuchów. Trzeba tylko sprawdzić, czy Twój kompilator jest ustawiony na kod źródłowy Unicode, aby działał poprawnie.

2

Warto również zauważyć, że szerokie znaki w C++ nie są tak naprawdę ciągami Unicode jako takimi. Są po prostu ciągami większych postaci, zwykle 16, ale czasami 32 bitami. To jest implementacja zdefiniowana, ale IIRC możesz mieć 8-bitowy wchar_t Nie masz prawdziwej gwarancji co do kodowania w nich, więc jeśli próbujesz zrobić coś takiego jak przetwarzanie tekstu, prawdopodobnie będziesz chciał typedef do najbardziej odpowiedni typ całkowity do jednostki Unicode.

C++ 1x posiada dodatkową obsługę unikodowymi postaci UTF-8 literałach kodujący łańcuch znaków (u8"text") i UTF-16 i UTF-32 typów danych (char16_t i char32_t IIRC), jak również odpowiednie stałe łańcuchowych (u"text" i U"text"). Kodowanie znaków określonych bez stałych \uxxxx lub \Uxxxxxxxx jest nadal zdefiniowane przez implementację (i nie ma obsługi kodowania złożonych typów łańcuchów poza literałami).

+0

Czy literówka "u" z małymi literami nie jest przeznaczona tylko dla postaci? – Tomasito665

6

Są tu dwie kwestie. Pierwszym z nich są dozwolone znaki w kodzie C++ (i komentarzach), takie jak nazwy zmiennych. Drugi to dozwolone znaki w łańcuchach i literałach łańcuchowych.

Jak wspomniano, kompilatory C++ muszą obsługują bardzo ograniczony zestaw znaków oparty na ASCII dla znaków dozwolonych w kodzie i komentarzach. W praktyce ten zestaw znaków nie działał zbyt dobrze z niektórymi europejskimi zestawami znaków (a zwłaszcza z niektórymi europejskimi klawiszami, które nie miały kilku znaków - jak nawiasy kwadratowe - dostępne), więc pojęcie digrafów i trigrafów było wprowadzony. Wiele kompilatorów akceptuje teraz więcej niż ten zestaw znaków, ale nie ma żadnej gwarancji.

Co do łańcuchów i literałów łańcuchowych, C++ ma pojęcie szerokiego łańcucha znaków i szerokiego łańcucha znaków. Jednak kodowanie tego zestawu znaków jest niezdefiniowane. W praktyce prawie zawsze jest to Unicode, ale nie sądzę, że jest tu jakakolwiek gwarancja. Literały łańcuchowe o szerokich ciągach znaków wyglądają jak literały literowe L ", a te mogą być przypisane do std :: wstring.


C++ 11 dodaje wyraźne wsparcie dla Unicode i napisowych, zakodowany jako UTF-8, UTF-16 big endian, UTF-16 little endian, UTF-32 big endian i UTF-32 little endian .

9

Oprócz postu litb, MSVC++ również obsługuje Unicode. Rozumiem, że pobiera kodowanie Unicode z BOM. To zdecydowanie wspiera kodu jak int (*♫)(); lub const std::set<int> ∅; Jeśli jesteś naprawdę w kodzie obfuscuation:

typedef void ‼; // Also known as \u203C 
class ooɟ { 
    operator ‼() {} 
}; 
+1

Może to być przydatne do pisania, na przykład, oprogramowania matematycznego, w którym kod źródłowy może być dopasowany do materiału źródłowego. Możesz to zrobić w Javie, która akceptuje kod źródłowy UTF-8. Jednak w C++ (i C) mogą wystąpić problemy z przekształcaniem tokenów spoza ASCII w nazwy symboli, które muszą być kompatybilne z resztą systemu operacyjnego - a nie tylko z cechą kompilatora. W C++ może to być podporządkowane manipulowaniu nazwami. –

2

W tym kontekście, jeśli uzyska MSVC++ ostrzeżenie C4819, wystarczy zmienić plik źródłowy kodowania do „UTF-8 z Bom” .

GCC 4.1 nie obsługuje tego, ale GCC 4.4 ma, a najnowsza wersja Qt używa GCC 4.4, więc użyj "UTF-8 z Bom" jako kodu źródłowego.