char类型的一个小坑

06 Dec 2017 | C/CPP | | ˚C

我们知道,在C中,整数类型(short,int,long)分为有符号和无符号两种,以int为例,单纯一个int代表有符号整型signed int,这里signed可以省略;无符号整型需要显示指明unsigned int

然而char是个例外。当然,C语言中,字符类型也分signed charunsigned 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 charunsigned 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);
             ^~

很明显,intsigned int是完全等同的,而charsigned char还有unsigned char之间互不相同。

在实际应用中,这种差别影响很小,因为几乎没有人会使用signed char,遇到类型转换的时候基本都是charunsigned char之间,如同intunsigned int一样,并不会造成理解上的困扰。

不过有一点,在C99中,有了stdint.h,定义了一系列类似int32_t这样的写明位宽的类型。这时候的int8_t由于是整数类型,因此等同于signed char,如果某些函数需要一个char *类型的指针,而实参变量是int8_t *,此处也要做个转换;而uint8_tunsigned char由于是直接typedef出来的,就没必要做类型转换了。


Older · View Archive (22)

DPDK non-EAL线程环境下的使用

Newer

记一个asio实现代理功能的设计思路