前几天遇到了这么个问题 ,在学习 unsigned char和char 和signed char的区别时 ,说char的类型到底是signed 还是unsigned 取决于编译器 。
当时写了一串代码 如下:
char a=-1; printf("%d\n",sizeof(a)); printf("%d\n",a); printf("%u\n",a);
先说%d 是将数据以int型的 十进制 格式输出;
%u 是将数据以unsigned int 的十进制格式输出;
那么为何会输出 4294967295呢? 再怎么理解 char 类型也只是占用了 一个字节 ,而这个结果分明是4个字节的最大整数啊!
为此当时还特意查看了 内存状况 如下:
查询了一下 cc在内存中表示的是 随机数 。
这就让我更难理解了:为何会输出一个 四个字节的最大int整数?
当时我百度的是 %d和%u的区别 ,,后来我知道 我的方向错了,,导致这个结果的原因是
printf 函数对于 unsigned 和signed char的区别。
1、printf中采用%d的格式输出 就是讲元素的内存块 以有符号的形式读出来,如char a=-1;
内存中就是 0xff ,这个数字用有符号的读出来 显示的就是 -1(原码,反码,补码的关系有讲)
而printf用%u的格式时 ,若被读的数是unsigned 类型,则不会有 “字符扩张”,若是signed 类型的(char short int long)都会有字符的扩展,而这个扩展在内存中是查看不到的,扩展成四个字节的数据, 具体如下:
若要读的数据 小于0,在内存中 符号位是1,扩展的时候,不足32位的都要在前面扩展出来的位补1(因为最前面是1,类似于<< >>左移右移时的方法),这个扩展出来的数 再以无符号int型十进制读。例如本例的-1 ,内存中是0xff ,扩展之后的就是0xff ff ff ff 这样再读就是4294967295了。
而如果是 1的话 内存中是0x01 (最前面是0) 所以扩展出来的也是0,即0x00 00 00 01,再读出来也是1.
#include<stdio.h> int main() { char c1=1,c2=-1; printf("%d\n",c1); printf("%d\n",c2); printf("%u\n",c1); printf("%u\n",c2); printf("#####################\n"); long l1=1,l2=-1; printf("%d\n",l1); printf("%d\n",l2); printf("%u\n",l1); printf("%u\n",l2); printf("#####################\n"); unsigned char c3=1,c4=-1; printf("%d\n",c3); printf("%d\n",c4); printf("%u\n",c3); printf("%u\n",c4); printf("#####################\n"); unsigned long l3=1,l4=-1; printf("%d\n",sizeof(l4)); printf("%d\n",l3); printf("%d\n",l4); printf("%u\n",l3); printf("%u\n",l4); return 0; }
运行结果:
注:最后的unsigned long l4=-1;在以%u输出的时候,结果也是4294967295,但是却并不是字符扩展的结果,因为它本来就占了4个字节,在内存中为0xFF FF FF FF,所以输出像是也进行了字符扩展一样。