问询C语言代码中变量i的取值变化及输出结果原因
代码中变量i的取值变化分析
让我一步步拆解这段代码里i的变化过程,核心是有符号字符的溢出截断和符号扩展这两个关键机制:
首先看完整代码:
/*how will the value of i be changed in output*/ void main() { int i = 150; char c = i; i = c; printf("%d", i); }
步骤1:初始赋值int i = 150;
在多数编译器中,int是32位的有符号整数,这里i直接存储十进制150,对应的二进制是:00000000 00000000 00000000 10010110
此时i的值就是150,没有任何问题。
步骤2:char c = i;——溢出截断
char类型在绝大多数主流编译器(比如GCC、MSVC)中是1字节(8位)的有符号整数,它的合法取值范围是-128 ~ 127。而150明显超出了这个范围,所以会发生截断操作:
只保留i的低8位二进制数据,也就是10010110。
现在这个8位二进制是有符号char的补码形式,最高位是1(代表负数),我们需要把它转换成十进制:
- 对符号位以外的部分取反:
01101001 - 加1得到原码:
01101010(对应十进制106) - 加上负号,最终c的值是**-106**。
步骤3:i = c;——符号扩展
当把有符号的char类型赋值给int类型时,C语言会自动执行符号扩展:
因为c是负数(二进制最高位为1),所以会把这个符号位1填充到int的所有高位,最终i的二进制变成:11111111 11111111 11111111 10010110
这个32位补码对应的十进制就是**-106**。
步骤4:printf("%d", i);
%d格式符会把i作为有符号整数输出,所以最终打印的结果就是-106。
补充说明:无符号char的情况
如果你的编译器默认char是无符号类型(这种情况比较少见),那结果会不同:
- 截断后的8位二进制
10010110作为无符号数是十进制150 - 赋值回i时不会做符号扩展,i的值还是150,最终输出150。
内容的提问来源于stack exchange,提问作者rahul chaudhary
相关产品推荐
相关产品推荐

