为什么wctype.h中的函数在没有setlocale()的情况下不能工作?
我的设置:glibc 2.24、gcc 6.2.0、UTF-8环境 考虑以下示例:为什么wctype.h中的函数在没有setlocale()的情况下不能工作?,c,glibc,wchar-t,setlocale,widechar,C,Glibc,Wchar T,Setlocale,Widechar,我的设置:glibc 2.24、gcc 6.2.0、UTF-8环境 考虑以下示例: #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;
#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;
}
现在删除setlocale()
,然后再次运行。结果不同:
$ gcc test.c
$ ./a.out; echo $?
1
从技术上讲,这里不需要使用setlocale()
,因为wctype.h
中的函数使用宽字符,这些字符具有固定的编码。(如果我们希望ctype.h
中的函数能够正确处理非ASCII字符,并且如果我们使用wchar.h中的字符转换函数来设置外部编码,那么setlocale()
是必需的。)
为什么没有setlocale()
,示例就不能工作?C标准说:
7.25宽字符分类和映射实用程序
这些函数的行为受当前区域设置的LC\CTYPE
类别的影响
此外(5.2.1字符集)
应定义两组字符及其相关的排序顺序:中的
写入哪些源文件(源字符集),以及在
执行环境(执行字符集)。每组又分为一组
基本字符集,其内容由本子条款给出,以及一个零或多个字符集
特定于区域设置的成员(不是基本字符集的成员)调用
扩展字符
然后(7.19通用定义
)
wchar\u t
这是一种整数类型,其值范围可以表示受支持区域设置中指定的最大扩展字符集的所有成员的不同代码
因此可能有许多扩展字符集,每个语言环境对应一个。因此,wchar_\t编码可能依赖于区域设置,因为编码是一组整数代码和一组字符之间的映射,而后者可能依赖于区域设置
鉴于上述情况,
必须依赖于区域设置。否则,标准将不得不强制要求有一个独立于语言环境的扩展字符集
在这个特定的示例中,宽字符常量L'\'
(一些整数代码)的值可能对应于也可能不对应于C语言环境下扩展字符集的任何成员
至于gcc和glibc的特定行为,在任何语言环境下,它们总是使用Unicode/ISO10646/UCS4作为扩展字符集,以简化操作。但是,他们不在C语言环境下对扩展字符进行分类,因为标准允许,他们不必这样做。(猜测如下)完整的Unicode分类表很大,只需要ASCII码的程序不必为其使用付费。否则它怎么知道该使用哪个字母表?@IgnacioVazquez-Abrams ISO10646-它针对宽字符进行了修复。ISO10646没有命名字母表。@IgnacioVazquez Abrams你注意到我使用了
en_US.UTF-8
,但符号不是来自en_US
,并且分类正确。所以,不,ISO10646确实命名了字母表。它不是en_-US字母表的一部分,但它在该语言中有一个定义的校对。我试图理解标准背后的推理。如果未指定,则区域设置为“C”
。因此,如果从OP中的示例中删除了setlocale()
,那么它无论如何都必须工作,但不能。是什么阻止了“C”
继承自i18n
,而“en_US”
继承自i18n
?(参见IgnacioVazquez Abrams对OP的评论)
$ gcc test.c
$ ./a.out; echo $?
1