我已经读过Order of evaluation,但我不太理解。该顺序是指运行时的执行顺序还是源代码中的逻辑顺序?
让我们看一下下面的代码段:
void f()
{
int a = 10; // A
int b = 20; // B
//...
}
这是否意味着在表达式A
之前对表达式B
进行了排序?
并且C ++编译器是否可以按如下所示重新排序代码?
void f()
{
int b = 20; // B
int a = 10; // A
//...
}
如果编译器确实按上述方式对代码进行了重新排序,那么我们应该说表达式B
是在A
之前排序的吗?
答案 0 :(得分:4)
通常,只要结果与编译代码完全一样,编译器就可以做任何事情。
实际上,您的典型C / C ++编译器已启用任何合理的优化标志,并具有以下功能:
void f (void) {
int a = 20;
int b = 10;
}
将其简单地编译为:
f:
ret
换句话说,它将把它当作一个空函数。原因是该功能没有任何作用。这些变量已分配给它们,但它们的值从未使用过(从技术上讲,它们是死存储区),因此编译器可以忽略它们。
现在,让我们看一个更实际的例子:
void foo (int num, int * num2, int * num3) {
*num2 = num * 2;
*num3 = num * 3;
}
编译器可以对这些语句重新排序吗?答案是肯定的否。原因是num2
和num3
可能指向相同的地址(换句话说,您可以调用foo(3, &bar, &bar)
之类的函数),因此写入的顺序很重要。另一方面,仅在C语言中(而不在C ++语言中),我们可以这样写:
void foo (int num, int * restrict num2, int * restrict num3) {
*num2 = num * 2;
*num3 = num * 3;
}
在那种情况下,restrict
关键字告诉编译器指针必须指向不同的地址,因此可以对语句进行重新排序,因为无论执行顺序如何,结果都是相同的。