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;
}
答案 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 - 57
或57 - 42
。
编辑:我错过了未定义和未指定之间的区别,请参阅Jerry Coffins的答案以了解详细信息。