char*与unsigned char*指针疑问:为何打印UINT_MAX而非-128?
我在测试char*和unsigned char*指针时遇到了这个问题:
测试代码:
#include <stdio.h> void func(unsigned int max) { unsigned int* intptr = &max; printf("%u - %p\n", max, &max); printf("%u - %p\n\n", *intptr, intptr); printf("%u - %p\n", *((char*)intptr), ((char*)intptr)); printf("%u - %p\n", *((signed char*)intptr), ((signed char*)intptr)); printf("%u - %p\n", *((unsigned char*)intptr), ((unsigned char*)intptr)); } int main(void) { unsigned int max1 = 0b00000000000000000000000001111111; unsigned int max2 = 0b00000000000000000000000011111111; func(max1); printf("\n\n\n\n"); func(max2); return 0; }
运行输出:
127 - 0x7ffc9712c53c 127 - 0x7ffc9712c53c 127 - 0x7ffc9712c53c 127 - 0x7ffc9712c53c 127 - 0x7ffc9712c53c 255 - 0x7ffc9712c53c 255 - 0x7ffc9712c53c 4294967295 - 0x7ffc9712c53c 4294967295 - 0x7ffc9712c53c 255 - 0x7ffc9712c53c
当前环境是小端模式,显然char在处理128以上的值时出现了溢出,但为什么用%u格式化输出时显示的是UINT_MAX(4294967295)而非-128?
问题解析
你的环境中
char是有符号类型
C标准中char可以是有符号或无符号,从输出判断,你的环境默认char等价于signed char。当读取max2的低字节(0xff)时,这个值作为有符号char会被解释为**-1**(0xff是8位有符号数的补码表示-1),而不是-128(-128的补码是0x80)。整数提升与
printf的类型匹配问题
当你把char或signed char类型的-1传递给printf时,会触发整数提升:因为char的位数小于int,有符号char的-1会被扩展为int类型的-1(符号位填充高位,二进制全为1)。而
%u格式符要求对应参数是unsigned int类型,printf会把传入的int类型-1直接当作unsigned int解析。int类型-1的二进制补码和unsigned int的UINT_MAX完全一致,所以输出就是4294967295。unsigned char的情况对比
unsigned char的0xff就是255,整数提升后是int类型的255,用%u输出时,int的255会被转换为unsigned int的255,所以输出符合预期。补充:为什么不是-128?
你的max2低字节是0xff,对应的有符号char值是-1,而-128对应的是0x80字节。只有当读取的字节是0x80时,有符号char才会是-128,此时用%u输出同样会得到UINT_MAX(因为int的-128提升后补码高位全1,转unsigned int就是UINT_MAX)。
内容的提问来源于stack exchange,提问作者programk5er

