一行中函数调用的执行顺序 - 未定义?

时间:2014-06-22 05:21:51

标签: c++ c

p.77 K& R C表示以下程序的输出未定义,但当前版本的Xcode没有发出警告。目前的标准还没有定义吗?在C ++中怎么样? Java和C#中类似程序的加分点。

#include <stdio.h>

int my_m()
{
    static int n = 0;
    static int m[] = { 42, 57 };
    return n++ % 2 == 0 ? m[0] : m[1];
}
int main()
{
    printf("%d" , my_m() - my_m());

    return 0;
}

2 个答案:

答案 0 :(得分:5)

结果实际上并未定义,只是未指定。

不同之处在于,未定义的行为意味着任何都可能发生,包括似乎与程序中的任何内容完全无关的行为。经典的一句话是它“让恶魔飞出你的鼻子。”

未指定意味着您无法知道将首先评估my_m的哪个调用,哪个将被评估,将< sup> 1 一次调用然后另一次调用。一个调用将开始并运行完成,然后另一个调用将开始并运行完成 - 两个将不会交错或类似的任何东西。唯一不可预测的是 order ,其中进行了两次调用(是的,根据当前的C和C ++标准,订单仍然是100%不可预测的。)

在C#和Java中,评估顺序从左到右指定。


或者至少它会像它一样。 C和C ++都遵循通常所谓的“似乎规则”,它允许编译器以不同的方式执行操作,只要它以维护指定的外部可见行为的方式执行。 功能

答案 1 :(得分:2)

编译器不会警告您所有未定义的程序。在以下行中:

printf("%d" , my_m() - my_m());

未指定调用my_m()的顺序。编译器可能决定先调用第一个或第二个调用。由于该函数在第一次调用时返回42,在第二次调用时返回57,因此结果为42 - 5757 - 42

编辑:我错过了未定义和未指定之间的区别,请参阅Jerry Coffins的答案以了解详细信息。