这个程序的输出是怎样的?

问题描述:

#include <stdio.h> 
int main() 
{ char i=0;    
    for(;i>=0;i++);  
    printf("%d",i);  
    return 0; 
} 

该程序的输出是-128。据我了解,字符变量会溢出,所有位将为0.并且取二进制补码将再次为0.有人可以解释这个过程吗?这个程序的输出是怎样的?

编辑:只是为了澄清,这不是我的程序。这是一场竞争性考试中的编程问题。

+2

您可能有*未定义的行为*。溢出有符号整数变量会导致UB。 'char'可以是'signed'或'unsigned'。 –

+1

首先,您应该修复代码。这是标记C和代码显然是C除了包含和命名空间的东西,这不属于这里。 (把#include '代替) –

+2

如果你可以完全按照你的问题所示编译代码,那么你使用的是C++编译器。用C++编译器编译C代码是一个坏主意。 –

您对溢出的假设是不正确的。溢出无符号类型将所有位设置为零,但溢出有符号类型为未定义,所以它可能会导致任何值。

你得到的结果是什么,因此要看你的(编译器)实现。如果

  • 你实现了签署char这可能解释。
  • A char有8位。
  • 负数用2的补码表示。
  • 溢出带符号的值会造成环绕。 (这是使用2的补数的简单实现的结果,见下文)

鉴于所有这些假设(请记住,这些没有仅由C指定),递增127以最大可能char值(表示为0111 1111)产生-128,最小可能值(表示为1000 0000)。

TL; DR - 你的代码是不确定的,不写这样的代码。

由于你的char被签名,它可以在-128到127之间(8位),并且你正在递增,直到达到最大值,然后溢出并成为 - 值,因为这就是写入负值的方式以位为单位。 看看下面的图片:

enter image description here

附:在循环内部进行一些打印,你也可以自己弄清楚。

+0

这张照片起初看起来很不错,但它实际上非常具有误导性,因为它呈现了非常不同的“多余的128”表示,*不是* 2的补充。 –

+0

我没有看着它只是试图给出具有8位数字表示的图形表示。我想新图像有更好的解释,但在一个较小的样本。感谢您指出了这一点。 – milorads

+0

感谢您的修复。像这样的图片很棒 - 只要它们准确无误! –

实际上在每次迭代中,循环将增加i,1,这导致我们到i = 127

  • 现在,让我们看看它的二进制表示0111-1111
  • 现在,如果我们增加1。然后
  • 0111-1111 + 0000-0001 = 1000-0000
  • 现在,分析这一点,MSB设置,这意味着它是一个负数
  • 负数是另存为2的补
  • 2的的1000-0000补= -127
  • 因此循环中断

希望你能得到它。

+0

虽然这很可能是发生了什么,但它需要所有*不保证的假设*我已在我的答案中列出。我不认为这是一个好主意,写一个答案,看起来这实际上是* defined *行为。 –