%d--是有符号整型数据的输出,对于有符号的short int型的数据的范围为:-32768~32767。
%u--是无符号的整形数据的输出形式。
+32767的16位二进制的表示为:0111 1111 1111 1111(最高位0表示符号位,0为正,1为负)
32768=0111 1111 1111 1111 + 1=1000 0000 0000 0000(进位被舍去),所以内存单元中存放的值是1000 0000 0000 0000,而我们知道整形数据在内存中是以其补码形式存放的,而-32768的补码就是1000 0000 0000 0000,所以若是按%d输出为-32768。
如果按%u形式输出的话,你所用的编译系统应该是这样处理的:
(1)首先将short int隐式转换为int,short int占2个字节,int占4个字节,那么需要进行符号位扩展,由于符号位是1,所以int的高16位全部用1扩展,所以在内存中存放的值为:
1111 1111 1111 1111(高16位全为1)1000 0000 0000 0000(低16位)
(2)由于是以%u的格式输出,所以编译系统就把符号位也当作数值位来处理了,那么
1111 1111 1111 1111 1000 0000 0000 0000的二进制数换算成10进制,值就是
4294934528。
将代码反汇编后看到调用printf()之前,执行了这个指令
movw $0x8000,0x1e(%esp)
movswl 0x1e(%esp),%eax
所以这里传参的时候将32768即0x8000进行了符号拓展,变为0xffff8000,就是无符号数的4294934528。(我也不知道为何要拓展,估计要么是为了对齐,要么就是printf参数的规定一种传值形式)然后这里把这个数打印了%u是说按32位无符号数形式打印,所以显示这个值。
因为是16位的short型。所以如果要打印最好用%hu,或者%hd,这里%h是short类型的意思。
应为%u对应unsigned int,你的数已经溢出。short[负数]被解释为unsigned short,然后以unsigned int输出。建议处理方法:
#include
int main()
{
short int i;
i = 32768;
printf("%d\n",~i+1);
return 0;
}