- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 ¹comp.lang.c++ Usenet 组中,我最近断言,基于我所知道的,Windows 的 16 位 wchar_t
,使用 UTF-16 编码,其中有时有两个这样的值(称为“代理对”)对于单个 Unicode 代码点是必需的,对于表示 Unicode 是无效的。
虽然 Unicode 联盟 2004 年的技术说明 12 为使用用于内部处理的 UTF-16,以及一系列令人印象深刻的软件。
显然,最初的意图似乎是每个代码点有一个wchar_t
值,这与C 和C++ 标准库的假设一致。例如。在 ³unix.org 的网页“ISO C 修正案 1 (MSE)”中,关于在 1995 年将 wchar_t
纳入 C 标准的修正案,作者认为
” The primary advantage to the one byte/one character model is that it is very easy to process data in fixed-width chunks. For this reason, the concept of the wide character was invented. A wide character is an abstract data type large enough to contain the largest character that is supported on a particular platform.
但事实证明,C 和 C++ 标准似乎并没有讨论支持的最大字符,而只讨论了支持的语言环境中最大的扩展字符集 : wchar_t
必须足够大以表示最大的此类扩展字符集中的每个代码点——但不是 Unicode,当没有 Unicode 语言环境时。
” [the
wchar_t
type] is an integer type whose range of values can represent distinct codes for all members of the largest extended character set specified among the supported locales.
这几乎与 C++ 标准中的措辞相同。这似乎意味着,在受支持的区域设置受限的情况下,wchar_t
确实可以很小,使用 UTF-8 编码可以降低到单个字节(这是一种噩梦,例如没有标准库字符分类函数会在 ASCII 的 A 到 Z 之外工作,但是嘿)。可能以下是比这更宽的要求:
” A wide character is a code value (a binary encoded integer) of an object of type
wchar_t
that corresponds to a member of the extended character set.
... 因为它指的是 扩展字符集,但该术语似乎没有在任何地方进一步定义。
至少对于 Microsoft 的 C 和 C++ 运行时,没有 Unicode 语言环境:使用该实现 setlocale
仅限于每个字符最多 2 个字节的字符编码:
setlocale
的文档:
” The set of available locale names, languages, country/region codes, and code pages includes all those supported by the Windows NLS API except code pages that require more than two bytes per character, such as UTF-7 and UTF-8. If you provide a code page value of UTF-7 or UTF-8,
setlocale
will fail, returningNULL
.
所以看来,与我所知道的相反,也与我的断言相反,Windows 的 16 位 wchar_t
在形式上是可以的。主要是由于 Microsoft 巧妙地缺乏对 UTF-8 语言环境或每个字符超过 2 个字节的任何语言环境的支持。但是真的是这样吗,16位的wchar_t
可以吗?
<支持>链接:
¹ 新闻:comp.lang.c++
² http://unicode.org/notes/tn12/#Software_16
³ http://www.unix.org/version2/whatsnew/login_mse.html
⁴ https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
最佳答案
wchar_t
现在不是,也从来不是 Unicode 字符/代码点。 C++ 标准并未声明宽字符串文字将包含 Unicode 字符。 C++ 标准并未声明宽字 rune 字将包含 Unicode 字符。事实上,该标准没有说明 任何 wchar_t
将包含的内容。
wchar_t
可以与可识别区域设置的 API 一起使用,但它们仅与实现定义的编码相关,而不是任何特定的 Unicode 编码。采用这些的标准库函数使用它们对实现编码的了解来完成它们的工作。
那么,16 位的wchar_t
合法吗?是的;该标准不要求 wchar_t
足够大以容纳 Unicode 代码点。
wchar_t
的字符串是否允许保存 UTF-16 值(或一般的可变宽度)?好吧,您可以制作 wchar_t
字符串来存储您想要的任何内容(只要它适合)。因此,就标准而言,问题是是否允许标准提供的用于生成 wchar_t
字符和字符串的方法使用 UTF-16。
好吧,标准库可以为所欲为;该标准不保证从任何特定字符编码到 wchar_t
的转换将是 1:1 映射。即使是通过 wstring_convert
进行的 char
->wchar_t
转换也不需要标准中的任何地方来生成 1:1 字符映射。
如果编译器希望声明宽字符集由 Unicode 的基本多语言平面组成,那么像这样的声明 L'\U0001F000'
将生成单个 wchar_t
。但是这个值是实现定义的,根据 [lex.ccon]/2:
The value of a wide-character literal containing a single c-char has value equal to the numerical value of the encoding of the c-char in the execution wide-character set, unless the c-char has no representation in the execution wide-character set, in which case the value is implementation-defined.
当然,C++ 不允许将代理项对用作c-char; \uD800
是一个编译错误。
标准中变得模糊的地方是如何处理包含字符集之外的字符的字符串。上面的文字表明实现可以做他们想做的事。然而,[lex.string]\16 是这样说的:
The size of a
char32_t
or wide string literal is the total number of escape sequences, universal-character-names, and other characters, plus one for the terminating U’\0’ or L’\0’.
我说这很模糊,因为没有说明如果字符串文字中的 c-char 超出目标字符集的范围时应该采取什么行为。
Windows 编译器(VS 和 GCC-on-Windows)确实会导致 L"\U0001F000"
的数组大小为 3(两个代理项对和一个 NUL 终止符)。这是合法的 C++ 标准行为吗?为超出字符集有效范围的字符串文字提供 c-char 是什么意思?
我会说这是标准中的漏洞,而不是那些编译器中的缺陷。它应该更清楚这种情况下的转换行为应该是什么。
无论如何,wchar_t
都不是处理 Unicode 编码文本的合适工具。它对于表示 任何形式 的 Unicode 不是“正式有效的”。是的,许多编译器将宽字符串文字实现为 Unicode 编码。但由于标准不要求这样做,您不能依赖它。
很明显,您可以将任何适合 wchar_t
的内容粘贴进去。因此,即使在 wchar_t
为 32 位的平台上,您也可以将 UTF-16 数据推送到其中,每个 16 位字占用 32 位。但是您不能将此类文本传递给任何需要宽字符编码的 API 函数,除非您知道这是该平台的预期编码。
如果您想使用 Unicode 编码,基本上不要使用 wchar_t
。
关于c++ - 16 位 wchar_t 是否正式代表完整的 Unicode?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39548465/
error C2440: 'initializing': cannot convert from 'TCHAR [260]' to 'std::basic_string,std::allocator>
首先。我想说,我不是 C++ 程序员。outlook 字符串在 visual studio 2015 中生成错误,并显示标题中的消息。 HWND windowHandle = (HWND)FindPr
我正在尝试检查一个 wchar_t * 是否等于另一个 wchar_t * 不区分大小写。有人可以把我放在正确的位置吗? 这是我尝试过的: wchar_t *vectored[80] = { ...
这是我的代码: wchar_t wbuffer[512]; wchar_t* wc = (wchar_t*) malloc(buffer_size); int buflen = 0;
如何正确转换这种方式? VARIANT varIndex; CString csIndex; //Index BSTR csIndex = (LPCSTR)(_bstr
我将以下代码作为我正在编写的字符串类中的私有(private)函数(它是从 wstring_convert “借来的”,并由我进行了一些修改): template std::string my_st
我有这样的东西: vector elements; 其中包含: 083938F8 083938FA 083938FC 083938FE 08393900 08393902 08393904 我想将它们
字符的签名不规范。因此,有signed char和unsigned char类型。因此,使用单个字符的函数必须使用既可以包含有符号字符又可以包含无符号字符的参数类型(此 类型选择为int),因为如果参
我在 Visual Studio C++ 2013 Community Edition 中遇到了一些奇怪的事情,这可能是编译器错误,也可能是我正在编写在没有警告的情况下进行编译的无效代码。 考虑以下片
我无法理解为什么某个隐式转换没有按我预期的那样工作。我有以下类(class) ref class ManagedWStringArrayWrapper { wchar_t** m_pointe
我有一个名为 DirToEmpty 的变量,它保存临时目录的路径。 我有另一个名为 TempBufDir 的变量,它将保持与 DirToEmpty 相同的值,但反斜杠被转义。 预期行为示例: wcha
我需要在附加 '\n' 后将多字节字符发送到套接字,但我拥有的是一个 const wchar_t*。我如何转换它? 最佳答案 如果您的问题是如何实际操作常量的内容,请考虑 const_cast . 关
我正在尝试使用语言环境方面将 wstring 转换为字符串,但我遇到了以下错误: test_facet.cpp: In function ‘int main()’: test_facet.cpp:14
我正在尝试使用 C++ 更改文件的属性我究竟做错了什么 ?代码完全拿下 https://learn.microsoft.com/en-us/windows/win32/stg/writeread-sa
我尝试将以下字符串数组传递给函数: const wchar_t *testTokens[] = { L"function", L"(",
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我尝试将阿拉伯字符存储为 wchar_t,然后将其打印到控制台,但无法使其工作。 我已将控制台设置为 UTF-8,如果我只是将阿拉伯字母输入控制台,它们就会正确显示(尽管未加入)。 我根据( How
我想存储一个包含扩展 ascii 表中字符的字符串,并打印它们。我尝试过: wchar_t wp[] = L"Росси́йская Акаде́мия Нау́к "; printf("%S", w
在C++ Visual Studio 2017中使用main函数是否错误如下: int main(int argc, wchar_t* argv[]) 因为我的程序可以接收特殊字符。 最佳答案 请阅读
我有这个运算符重载器。我的程序在创建新的 wchar_t 数组时崩溃。 myObject &operator += (const myObject &s) { wchar_t *cat = w
我是一名优秀的程序员,十分优秀!