下面我会根据几道例题详细分析其内部逻辑:
#负数在内存中以补码形式存储,打印出负数应先转换成原码;正数在内存中也以补码形式存储,但由于正数的原码,反码,补码相等,因此打印出正数原码即补码;
#%u为打印十进制的无符号数字;%d为打印十进制的有符号数字;
#有符号的char范围是-128->127;无符号char范围是0->255;
一.
1.首先,由于负数在内存中存储的是其补码。对于-1,其原码为1000000.....00001(共32位),则反码为11111......11110(符号位为1不变);故补码为原码加1,即11111.....11111;由小端存储知在char类型下其在内存中会存储位于低地址的第一个字节,即补码低位(右边)算起的8为->11111111;
2.对于char 以及signed char而言,由于要打印出整形类型(%d),因此要先进行整形提升,符号位位最高位1决定,因此其提升完成的补码为->11111....11111(32位);对应打印出的原码为1000.....0001;即-1;
3.对于unsigned char而言,由于11111111中第一个1不再是符号位,因此打印出整形进行整形提升后,在前面24位全部补充上0,即变成00000.....0011111111;由于提升后的整形最高位为0,因此为正数,由因为正数的原码,反码,补码相等,则打印值为255;
4.综上,答案为-1;-1;255;
二.
1.对于本例题,先求出a的原码,即为->10000...10000000,补码为1111....110000000,由于打印的a为char类型,由小端存储模式,其会取得地址的第一个字节(从右边数8个二进制位),即10000000;
2.由于a为char类型,因此最高位为符号位,故整形提升过程前面24个二进制位全部补上最高位1,变为->>1111....11110000000,此时打印出的是补码,应当再转换为原码再打印输出。
3.由于打印的是无符号数-->原码,补码,反码相同,则最后打印的二进制序列为1111....11110000000,因此最后的值为:4294967168。
三.下面给出有符号char范围在-128-<127的一个内在逻辑图:
根据上图,在下面的例题中:
1.由于有符号char的范围是-128到127,由上图可知:a=128=127+1=-128!
2.因此char a的补码为-> 10000000,进行整形提升->111....110000000;由于打印十进制的无符号数->原码等于补码->打印值与T2相同:4294967168。
四.
#对于有无符号数的相加,应当先转换成为补码(内存中为补码),再进行相加!
#本题大致思路:按照补码形式进行运算,最后格式化成为有符号整数!
1.先算出 i 和 j的补码,再相加,具体如下图所示:
2.由-"结果"处的补码算出最终的原码值;
3.最终打印出的结果是-10;
#无符号数容易使代码死循环;
五.
1.在本题中,由于i是以无符号数的格式进行输出,因此无论输入的是正数还是负数,都会以无符号的格式输出,
2.因此该程序会死循环;
六.
1.在本题中,由于无论输入怎样的整数,以unsigned char格式进行输出之后范围均在0-255之间;
2.因此同样会死循环;
七.
1.根据T3中关于有符号char范围在-128-<127的内在逻辑图可知: a[1000]中存储的是-128到127的数字;
2.由于strlen()函数会在找到'\0'时停下来,而'\0'的值为1;在a[1000]数组中;分别存储的数字为->
{-1,-2,-3,.....-128,127,126,125......3,2,1,0......};直到取到的值为0的时候停止,此时前面共出现了
255个数字;
3.因此答案为255;