这是一个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;
}
我需要完整的UTF-8支持,但即使在这个最简单的级别,我能以某种方式改进吗?为什么使用wint_t
而不是wchar
进行适当的更改?
答案 0 :(得分:17)
wint_t
能够存储wchar_t
的任何有效值。 wint_t
也能够接受评估WEOF
宏的结果(请注意,wchar_t
可能过于狭窄而无法保存结果。)
答案 1 :(得分:6)
正如@musiphil非常好地提出他的评论,我将尝试在此扩展,wint_t
和wchar_t
之间存在概念差异。
它们的不同大小是一个技术方面,它源于每个都具有非常独特的语义的事实:
wchar_t
足以存储字符或代码点。因此,它们未签名。它们类似于char
,在几乎所有平台中,它仅限于8位256值。所以宽字符串变量自然是这种类型的数组或指针。
现在输入字符串函数,其中一些需要能够返回任何 wchar_t
以及其他状态 。因此,他们的返回类型必须大于wchar_t
。所以使用了wint_t
,它可以表达任何宽字符和WEOF
。作为状态,它也可以是否定(通常是),因此wint_t
很可能是签名。我说&#34;可能&#34;因为C标准不授权它。但无论符号如何,状态值都必须在范围内wchar_t
。它们仅作为返回值使用,并且从不意味着存储这样的字符。
与&#34;经典&#34;的类比char
和int
非常适合清除任何混淆:字符串不是int []
类型,而是char var[]
(或char *var
)。并不是因为char
&#34;是int
&#34; 的一半大小,而是因为那是所在的> EM>
您的代码看起来是正确的:c
用于检查getwch()
的结果,因此它是wint_t
。如果它的值不是WEOF
,而是if
测试,那么将它分配给wchar_t
字符(或字符串数组,指针等)是安全的< / p>
答案 2 :(得分:2)
UTF-8
是Unicode的一种可能编码。它为每个字符定义1,2,3或4个字节。当您通过getwc()
读取它时,它将获取一到四个字节,并从它们组成一个Unicode字符 codepoint ,它将适合wchar
(可以是16甚至32位宽,具体取决于平台)。
但是由于Unicode值映射到0x0000
到0xFFFF
的所有值,因此没有值可以返回条件或错误代码。(有些人指出Unicode大于16 bits,这是真的;在那些情况下surrogate pairs被使用。但这里的重点是Unicode使用所有的可用值,而没有EOF。)
各种错误代码包括EOF(WEOF
),映射到-1。如果您将getwc()
的返回值放在wchar
中,则无法将其与Unicode 0xFFFF
字符区分开来(BTW,无论如何都是保留的,但是我离题)。
所以答案是使用更宽的类型,wint_t
(或int
),它至少包含32位。这给出了实际值的低16位,并且位设置在该范围之外的任何东西都意味着返回字符以外的其他内容。
为什么我们不总是使用wchar
而不是wint
?大多数与字符串相关的函数都使用wchar
,因为在大多数平台上,它的大小是wint
的1/2,因此字符串的内存占用量较小。