C ++ 11의 문자열 리터럴에 대한 유니 코드 인코딩


85

후속 관련된 질문 , 나는 C ++ 11의 새로운 문자 및 문자열 리터럴 유형에 대해 묻고 싶습니다. 이제 4 가지 종류의 문자와 5 가지 종류의 문자열 리터럴이있는 것 같습니다. 문자 유형 :

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

그리고 문자열 리터럴 :

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

질문은 이것입니다 : \x/ \u/ \U문자 참조는 모든 문자열 유형과 자유롭게 결합 할 수 있습니까? 모든 문자열 유형이 고정 너비입니까? 즉, 배열이 리터럴에 나타나는만큼 정확하게 요소를 포함 합니까? 아니면 \x/ \u/ \U참조에 대한 가변 바이트 수로 확장됩니까? 마 u""u8""문자열은 예를 들어, 의미를 인코딩 한 내가 말할 수있는 char16_t x[] = u"\U0010FFFF", 그리고 비 BMP 코드 포인트는 두 단위 UTF16 순서로 인코딩됩니다? 그리고 비슷하게 u8? (1)에서 외로운 대리자를 쓸 수 \u있습니까? 마지막으로 인코딩을 인식하는 문자열 함수가 있습니까 (즉, 문자를 인식하고 유효하지 않은 바이트 시퀀스를 감지 할 수 있음)?

이것은 약간의 개방형 질문이지만 새로운 C ++ 11의 새로운 UTF 인코딩 및 유형 기능에 대해 가능한 한 완전한 그림을 얻고 싶습니다.


4
GCC는 u"\U0010FFFF"서로 게이트 쌍으로 인코딩 합니다.
kennytm 2011

답변:


57

\ x / \ u / \ U 문자 참조는 모든 문자열 유형과 자유롭게 결합 할 수 있습니까?

호는 \x아무것도 사용할 수 있지만 \u하고 \U만 특이 UTF 인코딩 된 문자열에 사용될 수있다. 그러나 어떤 UTF로 인코딩 된 문자열을, \u그리고 \U당신이 맞는 볼 수 있습니다.

모든 문자열 유형이 고정 너비입니까? 즉, 배열이 리터럴에 나타나는만큼 정확하게 요소를 포함합니까, 아니면 \ x / \ u / \ U 참조에 대한 가변 바이트 수로 확장됩니까?

당신이 의미하는 방식이 아닙니다. \x,, \u\U문자열 인코딩을 기반으로 변환됩니다. 이러한 "코드 단위"(유니 코드 용어 사용. A char16_t는 UTF-16 코드 단위) 값의 수는 포함하는 문자열의 인코딩에 따라 다릅니다. 리터럴 u8"\u1024"은 2 char와 null 종결자를 포함하는 문자열을 만듭니다 . 리터럴 u"\u1024"은 1 char16_t과 null 종결자를 포함하는 문자열을 만듭니다 .

사용되는 코드 단위 수는 유니 코드 인코딩을 기반으로합니다.

u ""및 u8 ""문자열에 인코딩 의미가 있습니까? 예를 들어 char16_t x [] = u "\ U0010FFFF"라고 말할 수 있으며 비 BMP 코드 포인트는 2 단위 UTF16 시퀀스로 인코딩됩니까?

u""UTF-16으로 인코딩 된 문자열을 만듭니다. u8""UTF-8로 인코딩 된 문자열을 만듭니다. 유니 코드 사양에 따라 인코딩됩니다.

(1)에서 \ u로 고독한 대리자를 쓸 수 있습니까?

절대적으로하지. 사양은 \u또는에 대한 코드 포인트로 UTF-16 서로 게이트 쌍 (0xD800-0xDFFF)을 사용하는 것을 명시 적으로 금지합니다 \U.

마지막으로 인코딩을 인식하는 문자열 함수가 있습니까 (즉, 문자를 인식하고 유효하지 않은 바이트 시퀀스를 감지 할 수 있음)?

절대적으로하지. 글쎄요, 다시 말하겠습니다.

std::basic_string유니 코드 인코딩을 처리하지 않습니다. 확실히 UTF로 인코딩 된 문자열을 저장할있습니다 . 그러나 그들은 단지의 순서로 생각할 수있는 char, char16_t또는 char32_t; 특정 메커니즘으로 인코딩 된 일련의 유니 코드 코드 포인트로 생각할 수 없습니다. basic_string::length()코드 포인트가 아닌 코드 단위의 수를 반환합니다. 그리고 분명히 C 표준 라이브러리 문자열 함수는 완전히 쓸모가 없습니다.

그러나 유니 코드 문자열의 "길이"는 코드 포인트의 수를 의미하지 않습니다. 일부 코드 포인트는 이전 코드 포인트와 결합되는 "문자"(불행한 이름)를 결합합니다. 따라서 여러 코드 포인트가 단일 시각적 문자에 매핑 될 수 있습니다.

Iostreams는 실제로 유니 코드 인코딩 값을 읽고 쓸 수 있습니다. 이렇게하려면 로케일을 사용하여 인코딩을 지정하고 다양한 위치에 적절하게 삽입해야합니다. 이것은 말처럼 쉬운 일이며 방법을 보여줄 코드가 없습니다.


7
@Philipp : 아니요, 그렇지 않습니다. 유니 코드는 특히 UTF-16 서로 게이트를 위해 예약합니다. 그리고 언급했듯이 C ++ 0x의 사양에 따르면 해당 범위의 코드 포인트를 지정하려고하면 컴파일이 실패합니다.
Nicol Bolas 2011

12
귀하의 링크가 증명 되어 코드 포인트. Wikipedia를 신뢰하지 않는 경우 표준 3 장의 정의 9 및 10을 읽으십시오. 그러나 문자열 리터럴의 대리 코드 포인트는 규칙 § 2.4 / 2에 의해 C ++ 0x에서 금지됩니다.
Philipp

1
읽은 후에는 Surrogate 코드 포인트가 문자열 리터럴에서 허용되는지 확인합니다.
George Kourtis 2014-07-27

C11에서, \x예를 들어 U + 1F984를 들어, 아무것도 사용할 수 없습니다가 그리고, \ X 접두사 작동하지 않습니다 \u\U연타에이어야, ASCII 제어 문자와 함께 사용할 수 없습니다.
MarcusJ 2018
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.