2011-10-03 43 views
-3

所以我坚持这个问题。输出这个程序。内嵌?

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

据我 '一个' 应该是20 A = 6 + 6 + 8-8 然而,在执行我找到了答案是18.什么我做错了吗?一步一步的解释会很有帮助。

+0

请先发表您的想法 - 那么我们就可以纠正对经营者滥用你 –

+8

同样这样的问题。这只能是一个教练,总是问同样的问题吗? (请在C中搜索“序列点”)。 –

+0

为什么它是如此不明确?如果注意运营商的优先级,这是相当可计算的。它只是评估为18:1)我不能在表达式中改变它的值2)++我有更高的优先权,那么i ++(将在语句评估后应用)。 6 + 5 + 6 + 5 - 4 = 18 –

回答

3

这是不确定的行为。一个变量在序列点之间不能改变一次以上。你的程序可以输出任何东西任何答案说明否则是错误的。

+2

是的。这个程序甚至可能会杀死你的猫。 – ThiefMaster

+3

实际上,第1.33节。7从标准明确指出,没有程序可以杀死你的猫... –

0

表达要分配到a展品未定义的行为,特别是在其中递增/递减操作应用到它们的操作数的顺序。

1

在对C标准,它明确地说,一个编译器是免费的,只要优先规则,随后重新排列以任何方式表达。这意味着如果你有这个表达式:

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

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

在对C较老的标准,甚至说,编译器可以忽略括号,如果它想:

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

唯一肯定的方式来强制评估的一定顺序是使用临时变量:

temp0 = foo(); 
temp1 = bar(); 
x = temp0 + temp1 + baz(); 
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; 
} 

输出是5 6 5当用gcc编译和6 6 6当与Microsoft C/C++编译器来与Microsoft Visual Studio编译。

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

之前我引用来自ISO/IEC标准的有关章节,让我引用给K & R.东西在第2节。这本书的12(优先级和评估的顺序),作者写道,

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

操作员的操作数进行评估。 (唯一的例外是& &,||:?, 和 '')。例如,在像

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标准,并转到第438页获取附件C - 序列点。它列出了所有的序列点。 ;是其中之一。 +和++运算符不是序列点。

接着,读出部分5.1.2.3(程序执行),点2

Accessing a volatile object, modifying an object, modifying a 

文件或调用一个函数,它的任何这些操作都是 副作用,11),其是执行状态变化 环境。评估表达可能会产生副作用。在 执行序列中的某些特定点被称为序列 点,以前的评估的所有副作用应完成,并且 将不会发生后续评估的副作用。 (序列点的 总结附录C中给出)

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; 
+0

它甚至不那么确定性 - 你可以得到不同的结果为同一个编译器,取决于优化设置,周边代码等。 –

+0

确实。我只是去了最简单的两个例子。 –