我们知道,在C中,整数类型(short,int,long)分为有符号和无符号两种,以int为例,单纯一个int代表有符号整型signed int,这里signed可以省略;无符号整型需要显示指明unsigned int。
然而char是个例外。当然,C语言中,字符类型也分signed char和unsigned char,然而单写char的时候,究竟是有没有符号的?答案是不确定。
C99标准不在手,查了下cppreference-Fundamental types,其中是这么说的:
The signedness of char depends on the compiler and the target platform: the defaults for ARM and PowerPC are typically unsigned, the defaults for x86 and x64 are typically signed.
由实现定义。但这并不表明char完全等同于signed char和unsigned char中的一个。实际上,这三者完全是三个互不相同的类型,可以用一下程序验证:
test_char.c:
#include <stdio.h>
int main()
{
char c;
signed char sc;
unsigned char uc;
(void)(&c == &sc);
(void)(&c == &uc);
(void)(&sc == &uc);
int i;
signed int si;
unsigned int ui;
(void)(&i == &si);
(void)(&i == &ui);
(void)(&si == &ui);
return 0;
}
运行$ gcc -o test_char -std=c99 test_char.c,我们可以看到编译警告(不相同类型指针间的比较):
test_char.c: 在函数‘main’中:
test_char.c:8:12: 警告:比较不相关的指针时缺少类型转换
(void)(&c == &sc);
^~
test_char.c:9:12: 警告:比较不相关的指针时缺少类型转换
(void)(&c == &uc);
^~
test_char.c:10:13: 警告:比较不相关的指针时缺少类型转换
(void)(&sc == &uc);
^~
test_char.c:16:12: 警告:比较不相关的指针时缺少类型转换
(void)(&i == &ui);
^~
test_char.c:17:13: 警告:比较不相关的指针时缺少类型转换
(void)(&si == &ui);
^~
很明显,int和signed int是完全等同的,而char和signed char还有unsigned char之间互不相同。
在实际应用中,这种差别影响很小,因为几乎没有人会使用signed char,遇到类型转换的时候基本都是char和unsigned char之间,如同int和unsigned int一样,并不会造成理解上的困扰。
不过有一点,在C99中,有了stdint.h,定义了一系列类似int32_t这样的写明位宽的类型。这时候的int8_t由于是整数类型,因此等同于signed char,如果某些函数需要一个char *类型的指针,而实参变量是int8_t *,此处也要做个转换;而uint8_t和unsigned char由于是直接typedef出来的,就没必要做类型转换了。