char类型的一个小坑

1,096次阅读
没有评论

我们知道,在 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中的一个。实际上,这三者完全是三个互不相同的类型,可以用一下程序验证:

#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 出来的,就没必要做类型转换了。

正文完
 0
评论(没有评论)
验证码