C中的未定义行为

时间:2011-07-31 06:11:21

标签: c

  

可能重复:
  Parameter evaluation order before a function calling in C
  order of evaluation of function parameters

以下代码的输出结果如何:

n=5;
printf("%d %d\n", ++n, power(2, n));

输出= 32

不应该输出2 ^ 6 = 64?

不同的编译器会给出不同的结果吗?

3 个答案:

答案 0 :(得分:6)

函数参数的评估顺序是未指定。编译器可以按任何顺序计算参数,但它必须以某种特定顺序执行(因此这里没有 undefined 行为)。输出可以是32或64。

UPD:这是错误的,这里有UB,请参阅here

答案 1 :(得分:1)

与其他答案相反,代码可能确实表现出未定义的行为。

如上所述,函数参数的评估顺序在C中未指定。在您的程序中,您有一个由多个子表达式组成的表达式:

ex0(ex1, ex2, ex3(ex4, ex5));

这些子表达式之间只有部分排序:ex4ex5显然必须先评估ex3ex1ex2ex3必须在评估ex0之前进行评估。除此之外,子表达式的评估顺序是未指定的,由编译器决定评估子表达式的顺序。

某些有效的评估订单会产生未定义的行为。例如,如果在++n之前评估power(2, n),则结果是未定义的:在评估函数的所有参数之后但在之前或之间存在一个序列点,以及C语言标准非常清楚地说明(C99§6.5/ 2;强调我的):

  

在前一个和下一个序列点之间,一个对象的存储值最多只能通过表达式的一次修改一次。此外,先前的值应该是只读的,以确定要存储的值。

如果首先评估++n,则会违反此规则,因为n修改了++n,而n调用了power(2, n)而没有这两个步骤之间的序列点。

展示未定义行为的程序可能会产生任何结果:它可能会崩溃,可能会打印出意外的答案,或者它可能看起来像您期望的那样工作。由于您的程序可能表现出未定义的行为,因此很难确切地讨论您看到的实际行为。最好避免编写可能(或更糟,实际上)表现出未定义行为的程序。

答案 2 :(得分:0)

你的力量功能包含什么?我刚检查了C数学库的pow功能。我不得不把它投到< int>像这样;

#include <cstdio>
#include <cmath>
using namespace std;

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

输出:6 64

我使用的是Microsoft Compiler(由Visual Studio使用)。希望它有所帮助。