2016-11-09 82 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查看更新 –

相关问题