2016-11-09 124 views
3

我的設置:glibc 2.24,gcc 6.2.0,UTF-8環境。爲什麼wctype.h中的函數不能在沒有setlocale()的情況下工作?

請看下面的例子:

#include <wchar.h> 
#include <wctype.h> 
#include <locale.h> 
int main(void) 
{ 
    setlocale(LC_CTYPE, "en_US.UTF-8"); 
    wchar_t wc = L'я'; /* 00000100 01001111 */ 
    if (iswlower(wc)) return 0; 
    return 1; 
} 

編譯並運行它:

$ gcc test.c 
$ ./a.out; echo $? 
0 

現在除去setlocale()並再次運行。其結果是不同的:從技術上講,在這裏不需要

$ gcc test.c 
$ ./a.out; echo $? 
1 

setlocale(),因爲從與寬字符,其具有固定的編碼wctype.h功函數。 (不用說,setlocale()是必需的,如果我們想從ctype.h功能與非ASCII字符正常工作,如果我們用字符轉換函數從wchar.h - 設置外部編碼)

爲什麼沒有按範例沒有setlocale()

+1

如何知道要使用哪個字母? –

+0

@ IgnacioVazquez-Abrams ISO10646 - 它適用於寬字符。 https://www.gnu.org/software/libc/manual/html_node/Extended-Char-Intro.html –

+0

ISO 10646沒有命名字母表。 –

回答

1

C標準說:

7.25寬字符分類和映射公用事業<wctype.h>

...

這些函數的行爲由LC_CTYPE類別當前語言環境的影響。

此外(5.2.1字符集)

兩組字符和其相關聯的排序序列的應定義:該組中 其中源文件被寫入(源字符集),並在執行環境(執行字符集)中執行的解釋集 。每一組進一步被劃分爲一個 基本字符集,其內容通過本節中給出,以及一組零個或多個 區域設置特定的構件(其不是基本字符集的成員)稱爲 擴展的字符。

,然後(7.19通用定義<stddef.h>

wchar_t ,其是整數類型,其值的範圍可以表示不同的代碼所支持的語言中所指定的最大擴展字符集的所有成員

所以可能有很多擴展字符集,每個區域設置一個。因此,wchar_t編碼可能與語言環境有關,因爲編碼是一組整數代碼與一組字符之間的映射,後者可能與語言環境有關。

鑑於上述情況,<wctype.h>必須取決於語言環境。否則標準將不得不強制要求有一個與區域無關的擴展字符集。

在此特定示例中,寬字符常量L'я'(某些整數代碼)的值可能對應於C語言環境下擴展字符集的任何成員,也可能不對應。

至於gcc和glibc的具體行爲,爲了簡單起見,在任何語言環境下,它們總是使用Unicode/ISO10646/UCS4作爲擴展字符集。但是,它們不會在C語言環境下對擴展字符進行分類,因爲它們不需要(如標準所允許的那樣)。 (一個瘋狂的猜測如下)完整的Unicode分類表很大,只需要ASCII的程序不需要爲它們的使用付費。

+0

我想了解標準背後的推理。如果未指定,區域設置爲「C」。所以,如果在OP中的示例中刪除了'setlocale()',那麼它必須工作,但事實並非如此。什麼阻止''C''繼承'i18n',而''en_US''從'i18n'繼承? (見IgnacioVazquez-Abrams對OP的評論) –

+0

@IgorLiferenko查看更新 –

相關問題