char 的符号没有标准化。因此有signed char
和unsigned char
类型。因此,使用单个字符的函数必须使用可以同时包含有符号字符和无符号字符的参数类型(这个类型被选择为int
),因为如果参数类型是char
,我们会从编译器收到类型转换警告(如果 -Wconversion使用)在这样的代码中:
char c = 'ÿ';
if (islower((unsigned char) c)) ...
warning: conversion to ‘char’ from ‘unsigned char’ may change the sign of the result
(这里我们考虑如果 islower() 的参数类型是 char 会发生什么)
让它在没有显式类型转换的情况下工作的事情是从char
to自动提升int
。
此外,wchar_t
引入的 ISO C90 标准没有具体说明wchar_t
.
glibc 参考中的一些引用:
定义
wchar_t
为char
if
wchar_t
被定义为char
类型wint_t
必须被定义为int
由于参数提升。
因此,wchar_t
可以很好地定义为char
,这意味着必须适用于宽字符类型的类似规则,即,可能存在
wchar_t
肯定的实现,也可能存在wchar_t
否定的实现。由此得出,必须存在unsigned wchar_t
和类型(出于与存在和signed wchar_t
类型相同的原因)。unsigned char
signed char
私人通信表明允许实现仅支持具有 >=0 值的宽字符(与 的符号无关wchar_t
)。有人知道这是什么意思吗?薄是不是意味着当wchar_t
是16位类型时(例如),我们只能使用15位来存储宽字符的值?换句话说,符号扩展wchar_t
是否是有效值?另请参阅此问题。
此外,私人通信表明该标准要求 的任何有效值wchar_t
必须由 表示wint_t
。这是真的吗?
考虑这个例子:
#include <locale.h>
#include <ctype.h>
int main (void)
{
setlocale(LC_CTYPE, "fr_FR.ISO-8859-1");
/* 11111111 */
char c = 'ÿ';
if (islower(c)) return 0;
return 1;
}
为了使其可移植,我们需要强制转换为 '(unsigned char)'。这是必要的,因为char
可能是等价的signed char
,在这种情况下,设置了最高位的字节在转换为时将被符号扩展int
,从而产生一个超出范围的值unsigned char
。
现在,为什么这种情况与下面的宽字符示例不同?
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
int main(void)
{
setlocale(LC_CTYPE, "");
wchar_t wc = L'ÿ';
if (iswlower(wc)) return 0;
return 1;
}
我们需要在iswlower((unsigned wchar_t)wc)
这里使用,但是没有unsigned wchar_t
类型。
为什么没有unsigned wchar_t
和signed wchar_t
类型?
更新
标准是否说在以下两个程序中的转换unsigned int
和转换int
是正确的?(我只是在glibc中替换wint_t
了它们的实际含义)wchar_t
#include <locale.h>
#include <wchar.h>
int main(void)
{
setlocale(LC_CTYPE, "en_US.UTF-8");
unsigned int wc;
wc = getwchar();
putwchar((int) wc);
}
--
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
int main(void)
{
setlocale(LC_CTYPE, "en_US.UTF-8");
int wc;
wc = L'ÿ';
if (iswlower((unsigned int) wc)) return 0;
return 1;
}