这个节目的输出。融合?

时间:2011-10-03 18:54:21

标签: c post increment pre

所以我坚持这个问题。

int i=5,a;
a=++i + i++ + ++i + i++ - --i;
printf("%d",a);

根据我''应该是20。 一个= 6 + 6 + 8-8 然而,在执行时我发现答案是18.我做错了什么?一步一步的解释会有所帮助。

5 个答案:

答案 0 :(得分:3)

这是未定义的行为。变量不能在序列点之间多次更改。你的程序可以输出任何东西任何回答都是错误的。

答案 1 :(得分:3)

我已在我的博客文章http://blog.susam.in/2010/05/sequence-points.html

中详细介绍了这一点

我在这里发布一些摘录。

在C编程论坛中,一次又一次地询问特定类型的问题。这些问题有两件事激怒了论坛中经验丰富的程序员。首先,这类问题是如此常见,以至于许多人甚至不想回复它们,即使这意味着发布链接到另一个回答了类似问题的线程。其次,更重要的是,即使有人试图为问题提供正确的答案,也有很多人会忽略它并用错误的答案填补帖子。

问题通常涉及找到像这样的代码的输出。

#include <stdio.h>

int main()
{
    int i = 5;
    printf("%d %d %d\n", i, i--, ++i);
    return 0;
}

使用gcc编译时输出为5 6 5,使用Microsoft Visual Studio附带的Microsoft C / C ++编译器编译时输出为6 6 6。

此类C程序的行为未定义。在语句printf(“%d%d%d \ n”,i,i--,++ i);和a + = a ++ + a ++ ;,分号是唯一的序列点。 C保证给定表达式的所有副作用都由程序中的下一个序列点完成。如果在下一个序列点之前发生两个或多个副作用相互影响的操作,则行为未定义。使用不同的编译器进行编译时,此类代码的行为可能会有所不同。

在我引用ISO / IEC标准的相关章节之前,让我引用一些来自K&amp; R的内容。在本书的第2.12节(评价的优先顺序和顺序)中,作者写道,

C, like most languages, does not specify the order in which the
     

评估运算符的操作数。 (例外是&amp;&amp;,||,?:,   和','。)例如,在像

这样的声明中
x = f() + g();

f may be evaluated before g or vice versa; thus if either f or g
     

改变另一个所依赖的变量,x可以取决于   评估顺序。中间结果可以临时存储   变量以确保特定的序列。

他们在本节提供了另外一个例子。

One unhappy situation is typified by the statement

a[i] = i++;

The question is whether the subscript is the old value of i or the
     

新。编译器可以用不同的方式解释它,并生成   不同的答案取决于他们的解释。

如果您想了解更多信息,请下载ISO / IEC 9899 C标准,并转至附录C - 序列点的第438页。它列出了所有序列点。 ;是其中之一。 +和++运算符不是序列点。

接下来,阅读第5.1.2.3节(程序执行),第2点。

Accessing a volatile object, modifying an object, modifying a
     

文件,或调用执行任何这些操作的函数都是   副作用,11)这是执行状态的变化   环境。表达的评估可能产生副作用。在   执行序列中的某些指定点称为序列   要点,先前评估的所有副作用应完整   不得进行后续评估的副作用。 (一个   序列点的摘要见附件C.)

答案 2 :(得分:1)

在C标准中,它明确表示只要遵循优先规则,编译器就可以以任何方式重新排列表达式。这意味着如果你有这个表达式:

x = foo() + bar() + baz()

可以按任何顺序调用这三个函数,这是合法的。

在C的旧标准中,它甚至表示如果想要编译器可以忽略括号:

x = (foo() + bar()) + baz()

强制执行某种评估顺序的唯一可靠方法是使用临时变量:

temp0 = foo();
temp1 = bar();
x = temp0 + temp1 + baz();

答案 3 :(得分:0)

您分配给a的表达式表现出未定义的行为,特别是递增/递减操作应用于其操作数的顺序。

答案 4 :(得分:0)

取决于编译器执行所有操作的顺序。由于它依赖于编译器实现,因此没有“正确”的答案。

E.g。严格地离开 - >右:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     first   second  third  fourth  fifth
a = (6) + (6) + (8) + (8) - (7) = 21;

向右 - >向左:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     fifth   fourth third   second    first
a =  6 + 5 + 5 + 4 - 4 = 16;