所以我坚持这个问题。输出这个程序。内嵌?
int i=5,a;
a=++i + i++ + ++i + i++ - --i;
printf("%d",a);
据我 '一个' 应该是20 A = 6 + 6 + 8-8 然而,在执行我找到了答案是18.什么我做错了吗?一步一步的解释会很有帮助。
所以我坚持这个问题。输出这个程序。内嵌?
int i=5,a;
a=++i + i++ + ++i + i++ - --i;
printf("%d",a);
据我 '一个' 应该是20 A = 6 + 6 + 8-8 然而,在执行我找到了答案是18.什么我做错了吗?一步一步的解释会很有帮助。
这是不确定的行为。一个变量在序列点之间不能改变一次以上。你的程序可以输出任何东西任何答案说明否则是错误的。
是的。这个程序甚至可能会杀死你的猫。 – ThiefMaster
实际上,第1.33节。7从标准明确指出,没有程序可以杀死你的猫... –
表达要分配到a
展品未定义的行为,特别是在其中递增/递减操作应用到它们的操作数的顺序。
在对C标准,它明确地说,一个编译器是免费的,只要优先规则,随后重新排列以任何方式表达。这意味着如果你有这个表达式:
x = foo() + bar() + baz()
这三个函数可以按任何顺序调用,它是合法的。
在对C较老的标准,甚至说,编译器可以忽略括号,如果它想:
x = (foo() + bar()) + baz()
唯一肯定的方式来强制评估的一定顺序是使用临时变量:
temp0 = foo();
temp1 = bar();
x = temp0 + temp1 + baz();
我有一个详细的方式在我的博客文章在写本: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中给出)
具体取决于所订购的编译器中的一切。因为它是编译器实现相关的,有没有“正确”答案。
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;
它甚至不那么确定性 - 你可以得到不同的结果为同一个编译器,取决于优化设置,周边代码等。 –
确实。我只是去了最简单的两个例子。 –
请先发表您的想法 - 那么我们就可以纠正对经营者滥用你 –
同样这样的问题。这只能是一个教练,总是问同样的问题吗? (请在C中搜索“序列点”)。 –
为什么它是如此不明确?如果注意运营商的优先级,这是相当可计算的。它只是评估为18:1)我不能在表达式中改变它的值2)++我有更高的优先权,那么i ++(将在语句评估后应用)。 6 + 5 + 6 + 5 - 4 = 18 –