wchar_t到底能代表什么?

YSC*_*YSC 21 c++ unicode character-encoding

根据cppreference.com的文档wchar_t:

wchar_t - 用于宽字符表示的类型(请参阅宽字符串).要求足够大以表示任何支持的字符代码点(在支持Unicode的系统上为32位.一个值得注意的例外是Windows,其中wchar_t是16位并且保存UTF-16代码单元)它具有相同的大小,签名和对齐作为整数类型之一,但是是一个不同的类型.

标准说[basic.fundamental]/5:

Type wchar_­t是一种不同的类型,其值可以表示支持的语言环境中指定的最大扩展字符集的所有成员的不同代码.类型wchar_­t应具有与其他整数类型相同的大小,符号和对齐要求,称为其基础类型.类型char16_­tchar32_­t表示不同类型与大小相同,符号性,和对准如uint_­least16_­tuint_­least32_­t,分别在<cstdint>,称为基础类型.

所以,如果我想处理unicode字符,我应该使用wchar_t吗?

同样地,我怎么知道,如果一个特定的Unicode字符"支持"wchar_t

Jod*_*cus 13

所以,如果我想处理unicode字符,我应该使用 wchar_t吗?

首先,请注意编码不会强制您使用任何特定类型来表示某个字符.你可以char用来代表Unicode字符wchar_t- 你只需要记住,最多4 char秒将形成一个有效的代码点,具体取决于UTF-8,UTF-16或UTF-32编码,同时wchar_t可以使用1(UTF) -32在Linux上等)或最多2个一起工作(Windows上的UTF-16).

接下来,没有明确的Unicode编码.一些Unicode编码使用固定宽度来表示代码点(如UTF-32),其他(例如UTF-8和UTF-16)具有可变长度(例如,字母'a'肯定会使用1个字节,但是分开从英文字母表中,其他字符肯定会用更多的字节来表示).

因此,您必须决定要表示的字符类型,然后相应地选择您的编码.根据您要表示的字符类型,这将影响数据将占用的字节数.例如,使用UTF-32来表示大多数英文字符将导致许多0字节.UTF-8是许多拉丁语言的更好选择,而UTF-16通常是东亚语言的更好选择.

一旦您做出决定,您应该尽量减少转化次数并保持与您的决定一致.

在下一步中,您可以决定哪种数据类型适合表示数据(或者您可能需要哪种类型的转换).

如果你想在代码点的基础上进行文本操作/解释,char如果你有日本的汉字,肯定不是要走的路.但是,如果您只是想传达您的数据并且不再将其视为字节的定量序列,那么您可以随意使用char.

到处都是UTF-8的链接已作为评论发布,我建议你也看一下.另一个好的读物是每个程序员应该知道编码的内容.

到目前为止,C++中只有基本的语言支持(如char16_tchar32_t数据类型和u8/ u/ U文字前缀).因此选择一个用于管理编码(尤其是转换)的库肯定是一个很好的建议.


Bar*_*ani 8

wchar_t在Windows中使用UTF16-LE格式.wchar_t需要广泛的char函数.例如wcslen(const wchar_t*),strlen(const char*)std::wstring不是代替std::string

基于Unix的机器(Linux,Mac等)使用UTF8.这char用于存储,以及用于ASCII的相同C和C++函数,例如strlen(const char*)std::string(参见下面的评论std::find_first_of)

wchar_t在Windows中是2个字节(UTF16).但在其他机器上它是4个字节(UTF32).这让事情变得更加混乱.

对于UTF32,您可以std::u32string在不同系统上使用相同的内容.


您可以考虑将UTF8转换为UTF32,因为这样每个字符总是4个字节,您可能会认为字符串操作会更容易.但这很少是必要的.

UTF8的设计使得0到128之间的ASCII字符不用于表示其他Unicode代码点.这包括转义序列'\',printf格式说明符和常见的解析字符,

请考虑以下UTF8字符串.让我们说你想找到逗号

std::string str = u8"?,"; //3 code points represented by 8 bytes
Run Code Online (Sandbox Code Playgroud)

逗号的ASCII值是44,并且str保证只包含一个值为的字节44.要查找逗号,只需使用C或C++中的任何标准函数进行查找即可','

要查找?,您可以搜索字符串,u8"?"因为此代码点不能表示为单个字符.

某些C和C++函数无法与UTF8平稳运行.这些包括

strtok
strspn
std::find_first_of
Run Code Online (Sandbox Code Playgroud)

上述函数的参数是一组字符,而不是实际的字符串.

所以str.find_first_of(u8"?")不起作用.因为u8"?"是3个字节,find_first_of并将查找这些字节中的任何一个.这些字节中的一个可能用于表示不同的代码点.

另一方面,str.find_first_of(u8",;abcd")是安全的,因为搜索参数中的所有字符都是ASCII(str本身可以包含任何Unicode字符)

在极少数情况下可能需要UTF32(虽然我无法想象在哪里!)您可以使用std::codecvt将UTF8转换为UTF32来运行以下操作:

std::u32string u32 = U"012?"; //4 code points, represented by 4 elements
cout << u32.find_first_of(U"?") << endl; //outputs 3
cout << u32.find_first_of(U'?') << endl; //outputs 3
Run Code Online (Sandbox Code Playgroud)

边注:

您应该使用"无处不在的Unicode",而不是"无处不在的UTF8".

在Linux,Mac等中使用UTF8进行Unicode.

在Windows中,将UTF16用于Unicode.Windows程序员使用UTF16,他们不会在UTF8之间来回进行无意义的转换.但是在Windows中使用UTF8是合法的.

Windows程序员倾向于使用UTF8来保存文件,网页等.因此,在兼容性方面,非Windows程序员不必担心.

语言本身并不关心您要使用哪种Unicode格式,但在实用性方面,请使用与您正在处理的系统匹配的格式.


tes*_*ida 5

所以,如果我想处理unicode字符,我应该使用wchar_t吗?

这取决于你正在处理的编码.在UTF-8的情况下,你可以使用char和std :: string.UTF- 8表示最小编码单位是8位:从U + 0000到U + 007F的所有Unicode代码点仅由1个字节编码.从代码点U + 0080开始,UTF-8使用2个字节进行编码,从U + 0800开始,它使用3个字节,从U + 10000个4个字节开始.要处理这个可变宽度(1个字节 - 2个字节 - 3个字节 - 4个字节),char最适合.请注意,像strlen这样的C函数将提供基于字节的结果:"öö"实际上是一个双字符文本,但strlen将返回4,因为'ö'被编码为0xC3B6.

UTF- 16表示最小编码单位是16位:从U + 0000到U + FFFF的所有代码点都由2个字节编码; 从U + 100000开始使用4个字节.如果是UTF-16,你应该使用wchar_t和std :: wstring,因为你遇到的大多数字符都是2字节编码的.使用wchar_t时,你不能再使用像strlen这样的C函数了; 你必须使用像wcslen这样的宽字符等价物.

使用Visual Studio并使用配置"Unicode"构建时,您将获得UTF-16:TCHAR和CString将基于wchar_t而不是char.