C语言中int类型的一的补码(1s complement)运算及存储疑问
关于C语言整数按位取反运算的疑问解答
问题背景
代码:
int f = 45; printf("Value of %d is = %d",f,~f);
实际输出:
"Value of 45 is = -46"
已知编译器中int为4字节(32位),针对以下三个问题解答:
1. 整数45在机器中是按32位全量存储(高位补0),还是仅存储低8位?
int类型的大小固定为4字节(32位),不管数值本身需要多少位表示,都会占满整个int的存储空间。45的二进制是00101101,存储时会在高位补24个0,以32位全量存储:00000000 00000000 00000000 00101101。
2. 若int为4字节,int a=3会以32位的00000000000000000000000000000011存储,还是8位的00000011?int a=257的存储形式是32位的00000000000000000000000100000001,还是16位的0000000100000001?
两种情况都是以32位二进制存储:
int a=3的存储形式是32位的00000000 00000000 00000000 00000011int a=257的存储形式是32位的00000000 00000000 00000001 00000001
int类型的存储大小由编译器和系统决定,既然你的编译器中int是4字节,所有int变量都会占用32位空间,不会因为数值小就缩减位数。
3. 对45执行~(一的补码)运算时,所有位取反后为何结果是-46而非大正数?
核心原因是C语言中默认的int是有符号整数,采用补码规则存储和运算:
- 45的32位补码是
00000000 00000000 00000000 00101101,按位取反后得到11111111 11111111 11111111 11010010。 - 对于有符号整数,二进制最高位是符号位:1表示负数,0表示正数。上面取反后的结果最高位是1,所以是负数。
- 负数的补码转十进制的规则是:先对补码按位取反得到反码,再加1得到原数的绝对值,最后加上负号。对
11111111 11111111 11111111 11010010取反得到00000000 00000000 00000000 00101101(即45),加1后是46,所以最终结果是-46。 - 也可以用公式快速推导:对于有符号整数
x,~x = -x - 1,代入x=45,就是-45-1=-46。
内容的提问来源于stack exchange,提问作者user3737377
相关产品推荐
相关产品推荐

