这是一个ANSI C问题.我有以下代码.
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
int main()
{
if (!setlocale(LC_CTYPE, "")) {
printf( "Can't set the specified locale! "
"Check LANG, LC_CTYPE, LC_ALL.\n");
return -1;
}
wint_t c;
while((c=getwc(stdin))!=WEOF)
{
printf("%lc",c);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我需要完整的UTF-8支持,但即使在这个最简单的级别,我能以某种方式改进吗?为什么wint_t使用而不是wchar适当的更改?
Bra*_*lor 18
wint_t能够存储任何有效值wchar_t.A wint_t也能够接受评估WEOF宏的结果(注意a wchar_t太窄而不能保持结果).
正如@musiphil在他的评论中所做的那样,我将尝试在这里进行扩展,并且和之间存在概念上的差异.wint_twchar_t
它们的不同大小是一个技术方面,它源于每个都具有非常不同的语义:
wchar_t如果您愿意,它足以存储字符或代码点.因此,他们是未签名的.它们类似于char几乎在所有平台中,仅限于8位256值.因此,宽字符串变量自然是这种类型的数组或指针.
现在输入字符串函数,其中一些函数需要能够返回任何 wchar_t加上其他状态.所以他们的返回类型必须大于wchar_t.所以wint_t使用,它可以表达任何宽的char也WEOF.作为一种状态,它也可以是负面的(通常是负面的),因此wint_t很可能是签名的.我说"可能",因为C标准并没有强制要求它.但无论符号如何,状态值都必须超出范围wchar_t.它们仅用作返回值,并且从不意味着存储这些字符.
与"经典"的比喻char和int是伟大的,清除任何混乱:字符串不是类型int [],它们是char var[](或char *var).并没有因为char是"一半大小int",而是因为这是一个字符串什么是.
您的代码看起来是正确的:c用于检查的结果,getwch()所以它是wint_t.如果它的值不是WEOF,作为你的if测试,那么将它分配给一个wchar_t字符(或字符串数组,指针等)是安全的.
UTF-8是 Unicode 的一种可能的编码。它定义每个字符 1、2、3 或 4 个字节。当您通读它时getwc(),它将获取一到四个字节,并由它们组成一个 Unicode 字符代码点,该代码点适合 a wchar(可以是 16 位甚至 32 位宽,具体取决于平台)。
0x0000但由于 Unicode 值映射到从到 的所有值0xFFFF,因此没有剩余值可返回条件或错误代码。(有些人指出 Unicode 大于 16 位,这是事实;在这些情况下,使用代理项对。但这里的要点是 Unicode 使用所有可用值,没有为 EOF 留下任何值。)
各种错误代码包括 EOF ( WEOF),它映射到 -1。如果您将 a 的返回值放入getwc()a 中wchar,则无法将其与 Unicode0xFFFF字符区分开来(顺便说一句,无论如何,该字符都是保留的,但我离题了)。
因此,答案是使用更宽的类型,即wint_t(或int),它至少包含 32 位。这给出了实际值的低 16 位,任何设置在该范围之外的位都意味着发生了字符返回以外的情况。
为什么我们不总是使用wcharthen 来代替 呢wint?大多数与字符串相关的函数都使用wchar,因为在大多数平台上它的 \xc2\xbd 的大小为wint,因此字符串具有较小的内存占用量。