2021-03-26
发布日期:2021-05-13 22:26:45 浏览次数:26 分类:精选文章

本文共 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。

比如,编译以下程序:

#include 
static 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的区别同样关系到符号扩展。例如:

#include 
int 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) = 4
sizeof(a) = 2
-----------------------------begin p(char):
a = 4294954951 | -12345
0xffffffcf i = 4294967295 | -10
ffffffff 0xffffffff 0xffffffff 0xffffffff -1 > 0u: true
-----------------------------begin q(unsigned char):
a = 4294954951 | -12345
0xc7 i = 4294967295 | -10
xff ff ff ff -1 > 0u: true

char是有符号的,而unsigned char是无符号的。如果char类型的值大于127(即0x7F),在字符指针中会被视为负值,从而导致进一步操作时的不一致,这就是为什么编译警告会出现的原因。

上一篇:c语言字符串长度,占用字节大小,存放位置等问题
下一篇:大彩串口屏之LUA使用1

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2025年05月03日 10时19分14秒