这个程序的输出是怎样的?
#include <stdio.h>
int main()
{ char i=0;
for(;i>=0;i++);
printf("%d",i);
return 0;
}
该程序的输出是-128。据我了解,字符变量会溢出,所有位将为0.并且取二进制补码将再次为0.有人可以解释这个过程吗?这个程序的输出是怎样的?
编辑:只是为了澄清,这不是我的程序。这是一场竞争性考试中的编程问题。
您对溢出的假设是不正确的。溢出无符号类型将所有位设置为零,但溢出有符号类型为未定义,所以它可能会导致任何值。
你得到的结果是什么,因此要看你的(编译器)实现。如果
- 你实现了签署
char
这可能解释。 - A
char
有8位。 - 负数用2的补码表示。
- 溢出带符号的值会造成环绕。 (这是使用2的补数的简单实现的结果,见下文)
鉴于所有这些假设(请记住,这些没有仅由C指定),递增127
以最大可能char
值(表示为0111 1111
)产生-128
,最小可能值(表示为1000 0000
)。
TL; DR - 你的代码是不确定的,不写这样的代码。
由于你的char被签名,它可以在-128到127之间(8位),并且你正在递增,直到达到最大值,然后溢出并成为 - 值,因为这就是写入负值的方式以位为单位。 看看下面的图片:
附:在循环内部进行一些打印,你也可以自己弄清楚。
这张照片起初看起来很不错,但它实际上非常具有误导性,因为它呈现了非常不同的“多余的128”表示,*不是* 2的补充。 –
我没有看着它只是试图给出具有8位数字表示的图形表示。我想新图像有更好的解释,但在一个较小的样本。感谢您指出了这一点。 – milorads
感谢您的修复。像这样的图片很棒 - 只要它们准确无误! –
实际上在每次迭代中,循环将增加i
,1
,这导致我们到i = 127
。
- 现在,让我们看看它的二进制表示
0111-1111
。 - 现在,如果我们增加
1
。然后 -
0111-1111
+0000-0001
=1000-0000
- 现在,分析这一点,MSB设置,这意味着它是一个负数
- 负数是另存为2的补
- 2的的
1000-0000
补=-127
- 因此循环中断
希望你能得到它。
虽然这很可能是发生了什么,但它需要所有*不保证的假设*我已在我的答案中列出。我不认为这是一个好主意,写一个答案,看起来这实际上是* defined *行为。 –
您可能有*未定义的行为*。溢出有符号整数变量会导致UB。 'char'可以是'signed'或'unsigned'。 –
首先,您应该修复代码。这是标记C和代码显然是C除了包含和命名空间的东西,这不属于这里。 (把#include'代替) –
如果你可以完全按照你的问题所示编译代码,那么你使用的是C++编译器。用C++编译器编译C代码是一个坏主意。 –