your programing

C ++ wchar_t 및 wstrings에서 "잘못된"것은 무엇입니까?

lovepro 2020. 10. 5. 20:31
반응형

C ++ wchar_t 및 wstrings에서 "잘못된"것은 무엇입니까? 와이드 문자의 대안은 무엇입니까?


나는의 사용을 원망는 C ++ 커뮤니티 (는 Freenode에 특히 ## C ++)에서 많은 사람들을 보았다 wstrings하고 wchar_t, 그리고 윈도우 API에서의 사용. wchar_twstring에서 정확히 "잘못된"것은 무엇이며 국제화를 지원하려면 와이드 문자에 대한 몇 가지 대안은 무엇입니까?


wchar_t는 무엇입니까?

wchar_t는 모든 로케일의 char 인코딩이 모든 wchar_t가 정확히 하나의 코드 포인트를 나타내는 wchar_t 표현으로 변환 될 수 있도록 정의됩니다.

wchar_t 유형은 값이 지원되는 로케일 (22.3.1) 중에서 지정된 가장 큰 확장 문자 세트의 모든 멤버에 대한 고유 코드를 나타낼 수있는 고유 한 유형입니다.

                                                                               — C ++ [basic.fundamental] 3.9.1 / 5

이것은 wchar_t가 모든 로케일의 모든 문자를 동시에 나타낼 수있을만큼 충분히 클 필요 는 없습니다 . 즉, wchar_t에 사용되는 인코딩은 로케일마다 다를 수 있습니다. 즉, 한 로케일을 사용하여 반드시 문자열을 wchar_t로 변환 한 다음 다른 로케일을 사용하여 char로 다시 변환 할 수는 없습니다. 1

wchar_t를 모든 로케일 간의 공통 표현으로 사용하는 것이 실제로 wchar_t의 주요 용도 인 것처럼 보이므로 그렇지 않은 경우 무엇이 좋은지 궁금 할 것입니다.

wchar_t의 원래 의도와 목적은 문자열의 코드 단위에서 텍스트의 문자로의 일대일 매핑이 필요하도록 정의하여 텍스트 처리를 단순화하여 사용되는 것과 동일한 간단한 알고리즘을 사용할 수 있도록하는 것이 었습니다. ASCII 문자열로 다른 언어와 함께 작동합니다.

불행히도 wchar_t 사양의 문구는이를 달성하기 위해 문자와 코드 포인트 간의 일대일 매핑을 가정합니다. 유니 코드는 가정 2를 깨뜨 리므로 간단한 텍스트 알고리즘에도 wchar_t를 안전하게 사용할 수 없습니다.

즉, 휴대용 소프트웨어는 wchar_t를 로케일 간의 텍스트에 대한 공통 표현으로 사용하거나 간단한 텍스트 알고리즘을 사용할 수 없음을 의미합니다.

오늘날 wchar_t는 어떤 용도로 사용됩니까?

어쨌든 이식 가능한 코드는 많지 않습니다. __STDC_ISO_10646__이 정의 된 경우 wchar_t의 값은 모든 로케일에서 동일한 값을 가진 유니 코드 코드 포인트를 직접 나타냅니다. 따라서 앞에서 언급 한 로케일 간 변환을 안전하게 수행 할 수 있습니다. 그러나 대부분의 유닉스 플랫폼에서 정의하지만 Windows가 모든 로케일에서 동일한 wchar_t 로케일을 사용하더라도 Windows는 wchar_t를 이런 방식으로 사용할 수 있는지 결정하는 데에만 의존 할 수 없습니다.

Windows가 정의하지 않는 이유는 Windows가 __STDC_ISO_10646__wchar_t 인코딩으로 UTF-16을 사용하고 UTF-16이 서로 게이트 쌍을 사용하여 U + FFFF보다 큰 코드 포인트를 나타 내기 때문입니다. 즉, UTF-16이 __STDC_ISO_10646__.

플랫폼 별 코드의 경우 wchar_t가 더 유용 할 수 있습니다. Windows에서 필수적으로 필요합니다 (예 : wchar_t 파일 이름을 사용하지 않고는 일부 파일을 열 수 없음).하지만 Windows는 내가 아는 한 이것이 사실 인 유일한 플랫폼입니다 (따라서 wchar_t를 'Windows_char_t'로 생각할 수 있습니다).

돌이켜 보면 wchar_t는 텍스트 처리를 단순화하거나 로케일 독립 텍스트의 저장소로 유용하지 않습니다. 이식 가능한 코드를 이러한 목적으로 사용해서는 안됩니다. 이식 불가능한 코드는 일부 API가 필요하기 때문에 유용 할 수 있습니다.

대안

내가 좋아하는 대안은 UTF-8에 특별히 친숙하지 않은 플랫폼에서도 UTF-8로 인코딩 된 C 문자열을 사용하는 것입니다.

이런 식으로 플랫폼 전반에 걸쳐 공통 텍스트 표현을 사용하여 이식 가능한 코드를 작성하고, 의도 된 목적을 위해 표준 데이터 유형을 사용하고, 해당 유형에 대한 언어의 지원을받을 수 있습니다 (예 : 일부 컴파일러에서 작동하려면 일부 트릭이 필요하지만 문자열 리터럴). 표준 라이브러리 지원, 디버거 지원 (더 많은 트릭이 필요할 수 있음) 등. 넓은 문자를 사용하면 일반적으로이 모든 것을 얻는 것이 더 어렵거나 불가능하며 다른 플랫폼에서 다른 부분을 얻을 수 있습니다.

UTF-8이 제공하지 않는 한 가지는 ASCII에서 가능한 것과 같은 간단한 텍스트 알고리즘을 사용할 수 있다는 것입니다. 이 UTF-8에서는 다른 유니 코드 인코딩보다 나쁘지 않습니다. 사실 UTF-8의 다중 코드 단위 표현이 더 흔하고 문자의 가변 너비 표현을 처리하는 코드의 버그가 UTF를 고수하려고 할 때보 다 발견되고 수정 될 가능성이 더 높기 때문에 더 나은 것으로 간주 될 수 있습니다. -32 NFC 또는 NFKC

많은 플랫폼이 기본 문자 인코딩으로 UTF-8을 사용하고 많은 프로그램이 중요한 텍스트 처리를 필요로하지 않으므로 이러한 플랫폼에서 국제화 된 프로그램을 작성하는 것은 국제화를 고려하지 않고 코드를 작성하는 것과 거의 다릅니다. 보다 광범위하게 이식 가능한 코드를 작성하거나 다른 플랫폼에서 작성하려면 다른 인코딩을 사용하는 API 경계에 변환을 삽입해야합니다.

일부 소프트웨어에서 사용하는 또 다른 대안은 UTF-16 데이터를 보유하는 서명되지 않은 짧은 배열과 같은 크로스 플랫폼 표현을 선택한 다음 모든 라이브러리 지원을 제공하고 단순히 언어 지원 비용 등을 감수하는 것입니다.

C ++ 11은 보조 언어 / 라이브러리 기능을 사용하여 wchar_t, char16_t 및 char32_t의 대안으로 새로운 종류의 와이드 문자를 추가합니다. 실제로 UTF-16 및 UTF-32가 보장되지는 않지만 주요 구현이 다른 것을 사용할 것이라고는 생각하지 않습니다. C ++ 11은 또한 UTF-8 지원을 개선합니다. 예를 들어 UTF-8 문자열 리터럴을 사용하면 VC ++를 속여서 UTF-8 인코딩 문자열을 생성 할 필요가 없습니다 ( u8접두사를 사용하는 대신 계속 그렇게 할 수 있음 ). .

피해야 할 대안

TCHAR : TCHAR은 레거시 인코딩을 가정하는 고대 Windows 프로그램을 char에서 wchar_t로 마이그레이션하는 데 사용되며 프로그램이 이전 천년에 작성된 경우가 아니면 잊어 버리는 것이 가장 좋습니다. 이식 가능하지 않으며 인코딩 및 데이터 유형에 대해 본질적으로 불특정하여 TCHAR 기반이 아닌 API에서 사용할 수 없습니다. 목적이 wchar_t로 마이그레이션하는 것이기 때문에 위에서 본 것은 좋은 생각이 아니므로 TCHAR를 사용하는 데 아무런 가치가 없습니다.


1. wchar_t 문자열로 표현할 수 있지만 어떤 로케일에서도 지원되지 않는 문자는 단일 wchar_t 값으로 표현할 필요가 없습니다. 이것은 wchar_t가 특정 문자에 대해 가변 너비 인코딩을 사용할 수 있음을 의미하며, wchar_t의 의도에 대한 또 다른 명백한 위반입니다. wchar_t로 표현할 수있는 문자는 로케일이 해당 문자를 '지원'한다고 말하기에 충분하지만,이 경우 가변 너비 인코딩은 합법적이지 않으며 Window의 UTF-16 사용은 부적합합니다.

2. 유니 코드를 사용하면 여러 문자를 여러 코드 포인트로 표현할 수 있으므로 간단한 텍스트 알고리즘에 대해 가변 폭 인코딩과 동일한 문제가 발생합니다. 구성된 정규화를 엄격하게 유지하더라도 일부 문자에는 여전히 여러 코드 포인트가 필요합니다. 참조 : http://www.unicode.org/standard/where/


wchar_t에는 "잘못된"것이 없습니다. 문제는 NT 3.x 시절에 마이크로 소프트가 유니 코드가 좋다고 결정했고, 유니 코드를 16 비트 wchar_t 문자로 구현했다는 것입니다. 따라서 90 년대 중반의 대부분의 Microsoft 문헌은 유니 코드 == utf16 == wchar_t와 거의 동일합니다.

슬프게도 전혀 그렇지 않습니다. "와이드 문자"는 모든 상황에서 모든 플랫폼에서 반드시 2 바이트 아닙니다 .

This is one of the best primers on "Unicode" (independent of this question, independent of C++) I've ever seen: I highly recommend it:

And I honestly believe the best way to deal with "8-bit ASCII" vs "Win32 wide characters" vs "wchar_t-in-general" is simply to accept that "Windows is Different" ... and code accordingly.

IMHO...

PS:

I totally agree with jamesdlin above:

On Windows, you don't really have a choice. Its internal APIs were designed for UCS-2, which was reasonable at the time since it was before the variable-length UTF-8 and UTF-16 encodings were standardized. But now that they support UTF-16, they've ended up with the worst of both worlds.

참고URL : https://stackoverflow.com/questions/11107608/whats-wrong-with-c-wchar-t-and-wstrings-what-are-some-alternatives-to-wide

반응형