关于char类型变量以%u和赋给int输出的位扩展问题

图片说明

129的二进制为10000001
4294967169的二进制为11111111111111111111111110000001

按我了解到的位扩展方式理解。
当无符号i=4294967169 (二进制 11111111 11111111 11111111 10000001)
那么有符号的i应该为 -2147483521(二进制 1111111 11111111 11111111 10000001)
可用VS运行得出的是-127,也就是没有前面24个1得出来的。
寻求大神解释详细原因。

(顺带问一句,以%u输出,就是以无符号的int输出,所以才需要位扩展吗?)

你有一些最基本的概念还不清楚。
首先,负数在计算机里是怎么表示的,这个要搞清楚,是符号位1+补码,而不是原码
我们用最简单的4位数字表示
-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 的二进制分别如下:
1000 1001 1010 1011 1100 1101 1110 1111 0000 0001 0010 0011 0100 0101 0110 0111
可以概括出如下结论:
0的二进制是0
负数的二进制符号位是1,其余是 取反(原码-1),比如-2,它的原代码是 010,-1就是001,取反就是110,所以最后就是1110
因此,-2147483521的二进制表示应该是10000000000000000000000001111111,而不是1111111111111111111111110000001
如果我们把有符号、无符号的数字按照相同的二进制对照下,还是4位,那么就是
-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
对应
8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7
我们可以发现,对于负数,16+有符号数=无符号数。比如16-8=8,16-7=9...
其中16是2的4次方
我们也可以推广到32位,此时我们需要算出2的32次方,就是4294967296, 那么就是
有符号的-127转换为无符号的数就是4294967296-127=4294967169,它的二进制就是11111111111111111111111110000001了。

最后,上机验证下:
刚才说了,10000000000000000000000001111111才是-2147483521
它可以拆分成4个字节,分别是10000000 000000000 0000000 01111111,用16进制表示分别是0x80 0x0 0x0 0x7f
在x86处理器里,整数的字节顺序是倒过来的,也就是0x7f,0,0,0x80

 int _tmain(int argc, _TCHAR* argv[])
{
    unsigned char arr[] = {0x7f,0,0,0x80};
    int* i = (int *)arr;
    printf("%d\n", *i);
    return 0;
}

输出
-2147483521
Press any key to continue . . .

我稍后详细回答你这个问题。