2009-07-04 58 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字符(或字符串數​​組,指針等)是安全的。