signed/unsigned关键字
1:char 类型默认是signed
★如下代码:
char a[1000];
int i;
for(i=0;i<1000;i++)
{
a[i]=-1-i;
}
printf("%d\n",strlen(a));//在用strlen运算时,从数据起始,直至遇到第一个\0
打印结果:255
●分析过程如下:
a[0]= -1,对应的补码为 0xff 即 1 1111111
a[1]= -2,对应的补码为 0xfe即 1 1111110
…
a[127]= -1 – 127= -128,对应的补码为 0x80即 1 0000000
a[128]= -1 – 128= -129 // -129需要9位才能存储,而char只有8位,故发生溢出,高位舍弃:
//首先,计算机计算-1 – 128 得到 -129 。这个过程是不存在舍弃问题的。
//第二步,把- 129 赋值给a[128] 就出现了问题。因为a[128]是一个char类型,只有8 位,无法完全容纳- 129.只能把高位丢弃。
//-129 对应的补码为:1 0 1 1 1 1 1 1 1,现在丢掉高位,即截取后8位得到:
0 1 1 1 1 1 1 1即0x7f。注意,这是一个正数127.
接着计算a[129]
a[129]= -1 – 129 = -130//同样-130无法用8位来表示
// -130的补码为 1 0 1 1 1 1 1 1 0,截取后8位得到:0 1 1 1 1 1 1 0即0x7e即正数126
…
a[255]=-1-255=-256。
//对应补码:1 1 0000 0000,截后8位(即存到char中的)为:00000000,即0x00即0。
a[256]= -1–256= -257。对应补码:1 0 1111 1111,截后8位为:1111 1111 即0xff即-1
a[257]= -1–257= -258。对应补码:1 0 1111 1110,截后8位为:1111 1110 即0xfe即-2
…
注意,这里发现从a[256]开始,又回到了a[0]的状态。相当于一个循环。(a[0]=a[256],a[1]=a[257]…)
结果分析:
注意到,存到a[255]的值为0,而0对应的ascii码为 null,即结束符。所以在执行strlen(a)的时候,到a[255]就认为结束了。故打印出结果为255
★补充1:把int值赋给char类型
系统会把 int值对应的2进制,存到char变量的那8位内存上。
例如:char a=65
内存中a为:0100 0001,如果要用%c的格式打印a时,会把65对应的ascii字符打印出来,即’A’。如果要用%d的格式打印a,那么打印出:65
★补充2:char类型的赋值区别
char c1 = 0; //把数值0存到字符变量c1中
char c2 = ‘\0’;//把字符 ‘\0’ 即结束符,在ascii表中对应的十进制数即0,存到变量c2中
char c3 = ‘A’;//字符’A’在ascii表中对应的十进制数,即65存到变量3中
注意1:在ascii码表中,存在一个十进制数到字符的映射。
注意2:’\0’在ascii表中对应的十进制数为0,所以char c =0 等价于 char c=’\0’
★补充3:把一个负数,转成补码的方式。
先计算该绝对值的补码(正数的补码=原码),再将绝对值的补码,最高位改为1,剩余位取反加1
2:signed和unsigned之间的隐式类型转换
★如下代码:
int i=-20;
unsigned int j=10;
if(i+j>0)//编译器会自动的把i+j的结果转为unsigned类型,而unsigned一定是大于等于0的
printf("conversed~!\n");
else
printf("unconversed~!\n");
打印结果:conversed~!
结果分析:
在运算的时候,会把int值,隐式的转换为unsigned类型。
i= -20,-20的补码为:1…1110 1100即 0Xffffffed 。当将之转成unsigned类型的时候,这样i就会变成一个很大的正数…