
本文共 2740 字,大约阅读时间需要 9 分钟。
最近在项目中遇到了一个编译警告,是因为定义的变量为char[],而在使用时作为函数的unsigned char类型的参数调用。这个警告很容易避免,但char和unsigned char到底有什么区别呢,本文作一个简单的探讨。
在C中,默认的基础数据类型均为signed,如定义变量为int,long等,都为有符号的。如果要定义无符号类型,必须显式地在变量类型前加unsigned。
char和unsigned char的区别主要体现在内存存储和数据范围上。两者的内存大小都是一个字节(8位,2^8=256),但具体能表示的值范围有所不同。对于char来说,最高位是符号位,因此能表示的范围是-128~127;而unsigned char没有符号位,范围是0~255。
在实际使用中,如普通的赋值、读写文件和网络字节流都没有区别。不管变量是char还是unsigned char,处理结果都相同。但是当进行类型转换时,就会产生显著差异。具体来说,当将char类型变量赋值给int或long等有符号类型时,系统会进行符号扩展,即最高位如果是1,扩展时会全部填充1;而当使用unsigned char类型时,系统会进行无符号扩展,最高位始终填充0。
比如,编译以下程序:
#includestatic void func(unsigned char uc){ char c; int i, j; unsigned int ui, uj; c = uc; i = (int)c; j = (int)uc; ui = (unsigned int)c; uj = (unsigned int)uc; printf("%%c: %c, %c\n", c, uc); printf("%%x: %x, %x\n", c, uc); printf("%%u: %u, %u\n", ui, uj); printf("%%d: %d, %d\n", i, j);}int main(int argc, char *argv[]){ func(0x80); func(0x7f); return 0;}
运行结果如下:
%c: �, %c%%x: ffffff80, 80%%u: 4294967168, 128%d: -128, 128---------------------------%c: �, %c%%x: 7f, 7f%%u: 127, 127%%d: 127, 127
这表明,对于0x80(10000000二进制),作为char类型的变量赋值给int时会扩展为-128,而作为unsigned char类型变量赋值时扩展为128。而0x7f(01111111二进制),无论是char还是unsigned char,赋值结果都为127。
char和unsigned char的区别同样关系到符号扩展。例如:
#includeint main(int argc, char *argv[]){ unsigned char k = 0; int i = -1; short a = -12345; char *p; unsigned char *q; printf("sizeof(i) = %d\n", sizeof(i)); printf("sizeof(a) = %d\n", sizeof(a)); printf("-----------------------------\n"); printf("begin p(char):\n"); p = (char*)&a; printf("a = %u | %d\n", a, a); for(k=0; k< sizeof(a); k++) { printf("0x%x ", *(p++)); } printf("\n"); p = (char*)&i; printf("i=%u" | %d\n", i, i); for(k=0; k< sizeof(i); k++) { printf("-1 %c: %s\n", (-1 > 0u ? "true" : "false")); } printf("-----------------------------\n"); printf("begin q(unsigned char):\n"); q = (unsigned char*)&a; printf("a = %u | %d\n", a, a); for(k=0; k< sizeof(a); k++) { printf("0x%x ", *(q++)); } printf("\n"); q = (unsigned char*)&i; printf("i=%u" | %d\n", i, i); for(k=0; k< sizeof(i); k++) { printf("-1 > 0u: %s\n", (-1 > 0u ? "true" : "false")); } return 0;}
输出结果为:
sizeof(i) = 4sizeof(a) = 2-----------------------------begin p(char):a = 4294954951 | -123450xffffffcf i = 4294967295 | -10ffffffff 0xffffffff 0xffffffff 0xffffffff -1 > 0u: true-----------------------------begin q(unsigned char):a = 4294954951 | -123450xc7 i = 4294967295 | -10xff ff ff ff -1 > 0u: true
char是有符号的,而unsigned char是无符号的。如果char类型的值大于127(即0x7F),在字符指针中会被视为负值,从而导致进一步操作时的不一致,这就是为什么编译警告会出现的原因。
发表评论
最新留言
关于作者
