【问题标题】:Interchanging statements in for loop在 for 循环中交换语句
【发布时间】:2012-07-27 15:22:32
【问题描述】:

这是 C 语言中的代码行。
这里循环的条件是++i。
那么编译器如何决定考虑哪个条件,因为这里其他两个作为条件出现?

char i=0;
for(i<=5&&i>-1;++i;i>0)
    printf("%d",i);

输出

1234..127-128-127....-2-1

【问题讨论】:

  • 请注意,程序的行为是实现定义的(或可能未定义的),并且取决于(除其他外)char 类型的符号,char 可表示的值范围、intunsigned int,以及从一种有符号类型到另一种有符号类型的缩小转换的实现定义的行为。简而言之:编写这样的代码是危险的。

标签: c


【解决方案1】:

for 语句的工作方式如下:

for (X; Y; Z)
{
    ...
}

翻译成

X;
while (Y)
{
    ...
    Z;
}

所以你的代码从:

char i=0;
for(i<=5&&i>-1;++i;i>0)
    printf("%d",i);

到:

char i = 0;
i<=5 && i>-1;    // X
while (++i)      // Y
{
    printf("%d", i);
    i > 0;       // Z
}

如您所见,标有XZ 的行完全没有用。因此:

char i = 0;
while (++i)
    printf("%d", i);

这意味着它将从 1 到 ++i 的结果为零时打印。

如果您的编译器中的 char 已签名,则该行为留给实现,即使它很可能会溢出到负值并一直工作到零。

如果char 是正数,这将打印正数,直到溢出回0。

【讨论】:

  • C11,第 3.4.3.3 节(示例):未定义行为的示例是整数溢出行为。
  • Nit:只有当char 被签名并且 由int 表示的所有值也可以由char 表示(即,如果charint 由相同的位数表示)。如果charint 窄,则行为是实现定义的,因为没有溢出:char 操作数将提升为int 以执行递增,然后int 类型的结果将转换回char;该转换不会产生溢出,它具有实现定义的行为。
【解决方案2】:

它没有。它运行第一部分,i 被设置为任何副作用,然后在第二部分为 false 时终止,在这种情况下,当 i 为 0 时,然后在每个循环中运行第三部分。

所以编译器基本上将其重写为:

char i=0;
i<=5&&i>-1;
do {
     printf("%d",i);
     i>0;
} while ( (++i) != 0)

提示:记住 char 是有符号和二进制补码,所以我会选择 1,2,3....128,-127,-126....0

【讨论】:

  • “记住 char 是有符号的”或无符号:char 的有符号性是实现定义的。
  • @JamesMcNellis 并且不必是 8 位。但在这种情况下,OP 作为输出给出的值表明 char 是在他们的平台上签名的。我只是想向他们解释我是如何最终成为“假”的
【解决方案3】:

这里的循环终止条件是++i。这没有什么神秘之处。当我达到 0 时循环将停止(因为它将是“假”)

【讨论】:

  • 您回答了您自己的问题“那么编译器如何决定要考虑哪个条件,因为这里其他两个作为条件出现”。 for 循环的中间子句是终止测试 - ++i 在您的情况下。其他两个子句也是条件句这一事实无关紧要(但会让人类读者感到困惑)。编译器只是生成在适当的时间执行第一和第三子句的代码,它不查看结果
猜你喜欢
  • 2014-03-30
  • 1970-01-01
  • 2010-11-19
  • 2016-09-04
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2011-08-17
  • 2014-08-28
相关资源
最近更新 更多