我想了解char
和wchar_t
之间的区别?我了解wchar_t
使用了更多的字节,但是我可以得到一个明确的示例来区分我何时使用char
vs wchar_t
答案 0 :(得分:10)
绝不使用wchar_t
。
如果可能,请使用(某种数组)char
,例如std::string
,并确保它以UTF-8编码。
如果必须与不使用UTF-8的API进行交互,请使用char16_t
或char32_t
。否则不要使用它们;它们只提供虚幻的优势,并鼓励错误的代码。
请注意,很多的情况需要多个char32_t
来表示单个用户可见字符。 OTOH,使用带char
的UTF-8强迫你很早就处理可变宽度。
答案 1 :(得分:7)
从根本上说,当编码包含的符号多于wchar_t
时,请使用char
。
<强>背景强>
char
类型具有足够的容量来保存ASCII字符集中的任何字符(编码)。
问题是许多语言需要比ASCII帐户更多的编码。因此,代替127种可能的编码,需要更多。有些语言有超过256种可能的编码。 char
类型不保证大于256的范围。因此需要新的数据类型。
wchar_t
,a.k.a。宽字符,为编码提供了更多空间。
<强>摘要强>
当编码范围为256或更小时,使用char
数据类型,例如ASCII。当您需要超过256的容量时,请使用wchar_t
。
首选Unicode来处理大字符集(例如emojis)。
答案 2 :(得分:7)
简短的回答:
除非在与特定于操作系统的API交互时(基本上仅使用wchar_t
调用Windows API函数),否则不应在现代C ++中使用wchar_t
。
答案很长:
标准C ++库的设计意味着只有一种方法可以处理Unicode - 通过在char数组中存储UTF-8编码的字符串,因为几乎所有函数都只存在于char变体中(想想std::exception::what
)。
在C ++程序中,您有两个区域设置:
- std::setlocale
设置的标准C库区域设置
- std::locale::global
不幸的是,它们都没有定义打开文件的标准函数的行为(如std::fopen
,std::fstream::open
等)。操作系统之间的行为不同:
- Linux编码不可知,因此这些函数只是将char字符串传递给底层系统调用
- 在Windows上,在进行系统调用之前,使用特定于用户的语言环境将字符串转换为宽字符串
所有内容通常都适用于Linux,因为每个人都使用基于UTF-8的语言环境,因此传递给main
函数的所有用户输入和参数都将采用UTF-8编码。但是您可能仍需要显式地将当前语言环境切换为UTF-8变体,因为默认情况下C ++程序使用默认的"C"
语言环境启动。此时,如果您只关心Linux并且不需要支持Windows,则可以使用char数组和std::string
,假设它是UTF-8序列,并且所有内容都“正常”。
当您想要支持Windows时出现问题,因为此处您总是有其他第三语言环境:为当前用户设置的一个可以在“控制面板”中的某处配置。主要问题是这个语言环境永远不是unicode语言环境,所以不可能使用std::fopen(const char *)
和std::fstream::open(const char *)
等函数来使用Unicode路径打开文件。在Windows上,您必须使用在Windows上使用非标准Windows特定功能(如_wfopen
,std::fstream::open(const wchar_t *)
的自定义包装器。您可以查看Boost.Nowide(尚未包含在Boost中),看看如何做到这一点:http://cppcms.com/files/nowide/html/
使用C ++ 17,您可以使用std::filesystem::path
以便携方式存储文件路径,但在Windows上仍然存在:
std::filesystem::path::path(const char *)
在MSVC上使用特定于用户的区域设置,并且无法使其使用UTF-8。函数std::filesystem::u8string
应该用于构造UTF-8字符串的路径,但是很容易忘记这一点,而是使用隐式构造。std::error_category::message(int)
使用特定于用户的编码返回错误说明。所以我们在Windows上的内容是:
main(int, char**)
的参数已被破坏,绝不应使用。std::filesystem::path
已部分损坏,不应直接使用。std::generic_category
和std::system_category
返回的错误类别已被破坏,绝不应使用。如果您需要长期解决非平凡项目,我建议:
std::generic_category
和std::system_category
返回的标准错误类别,以便它们始终返回UTF-8编码的字符串。std::filesystem::path
,以便在将路径转换为字符串并将字符串转换为路径时,新类始终使用UTF-8。std::filesystem
中包含所有必需的功能,以便他们使用您的路径包装器和错误类别。不幸的是,这不会解决其他使用文件的库的问题,但是其中99%都会被破坏(不支持unicode)。
这就是C ++程序员的生活。 Microsoft可以通过允许我们将Windows运行时切换到基于UTF-8的语言环境来解决这个问题,但由于向后兼容性,它们不会这样做。
您可以查看此链接以获取进一步说明:http://utf8everywhere.org/