2009-07-04 70 views
11

这是一个ANSI C问题。我有以下代码。wchar_t vs wint_t

#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,并做了适当的更改?

回答

3

UTF-8是Unicode的一种可能编码。它为每个字符定义了1,2,3或4个字节。当你通过getwc()读取它时,它将读取一到四个字节,并从它们组成一个单一的Unicode字符码点,这将适合于wchar(其可以是16甚至32位宽,取决于平台)。

但是,由于Unicode值映射到从0x00000xFFFF的所有值,因此没有剩余的值可以返回条件或错误代码(有些人指出Unicode大于16位,这是真的;在这些案件surrogate pairs被使用。但这里的问题是,Unicode使用没有留下为EOF可用值所有

各种错误代码包括EOF(WEOF),这映射到-1。如果您要将getwc()的返回值设置为wchar,则无法将其与Unicode 0xFFFF字符区分开(无论如何,它都是保留的,但我是离题的)。

因此,答案是使用更宽型,wint_t(或int),其保持至少32位。这给出了实际值的低16位,并且任何位置在该范围外的任何事物都意味着发生了字符以外的其他事情。

为什么我们不总是使用wchar而不是wint?大多数与字符串相关的函数使用wchar,因为在大多数平台上它的大小是wint的1/2,所以字符串的内存占用量较小。

15

wint_t能够存储任何有效值wchar_t。 A wint_t也能够评估WEOF宏(注意wchar_t太窄而无法保留结果)。

+1

好的,谢谢。所以,简而言之:什么时候使用wchar_t更好?为什么不总是使用wint_t? – 2009-07-04 19:42:40

+10

`wint_t`是``wchar_t`什么`int`是`char`。尽管`getc()`返回`int`能够返回'EOF`,我们不会为窄字符串使用'int'数组。同样,即使`getwc()`返回`wint_t`能够返回`WEOF`,我们也不会为宽字符串使用`wint_t`数组。 – musiphil 2012-05-23 07:29:13

+2

@musiphil:你的评论应该是一个答案,它是唯一一个谈论它们之间的概念*差异的人。 – MestreLion 2015-03-05 19:38:52

6

由于@musiphil所以把好听他的评论,我将在这里展开,有wint_twchar_t之间的概念差异。

他们不同的尺寸是技术方面,从事实上每个人都有非常明显的语义得出:

  • wchar_t大到足以存储字符,或码点如果你喜欢。因此,他们是未签名的。它们类似于char,在几乎所有的平台上,它都限制在8位256值。所以宽字符串变量自然是这种类型的数组或指针。

  • 现在输入字符串功能,其中一些需要能够返回任何wchar_t加上附加状态。所以他们的退货类型必须大于wchar_t。因此使用wint_t,它可以表示任何宽字符,也可以表示WEOF。作为一个身份,它也可以是负数(通常是),因此wint_t最有可能是签名。我说“可能”,因为C标准没有要求它是。但不管符号如何,状态值需要以外的范围为wchar_t。他们只是作为回报价值有用,并且从未意味着这样的字符。

与类比“经典” charint是伟大的,清除任何混乱:字符串是int []类型的不是,他们是char var[](或char *var)。而不是因为charint的大小的一半”,但因为这是什么字符串

您的代码看起来正确:c用于检查getwch()的结果,因此它是wint_t。如果它的值不是WEOF,那么作为if测试,那么将它分配给wchar_t字符(或字符串数​​组,指针等)是安全的。