Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么wctype.h中的函数在没有setlocale()的情况下不能工作?_C_Glibc_Wchar T_Setlocale_Widechar - Fatal编程技术网

为什么wctype.h中的函数在没有setlocale()的情况下不能工作?

为什么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;

我的设置: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;
  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