C和C++标准规定执行顺序必须严格遵循源指令顺序。编译器可以自由地以任何顺序评估指令中的子表达式,但不能对用分号或冒号分隔的指令重新排序。
例如指令中:
A = A + B * C + D * E;
编译器可能会选择在 B*C 之前执行 D*E,或者在最后添加 A。
如果现在将相同的计算分成不同的指令:
int t1 = B * C;
t1 += D * E;
A += t1;
在这种情况下,编译器无法在 B * C 之后计算 D * E。
通常,这种代码会稍微慢一些,因为编译器无法针对特定硬件优化 CPU 指令的顺序。
我想做的是相反的方式。例如,如果一个展开的循环的主体显示为:
A[0] = B[0] * C[0];
A[1] = B[1] * C[1];
A[2] = B[2] * C[2];
A[3] = B[3] * C[3];
有没有办法告诉编译器这四个指令可以按任何顺序计算,因为它们对单独的数据进行操作?即使是不可移植的技巧也是受欢迎的。
最佳答案
The C and C++ standards specify that the order of execution must strictly follow the source instructions order.
不完全是。他们说程序的可观察行为 - 即 I/O 操作和对 volatile 对象的访问 - 必须就好像那样发生。只要不改变程序的行为,编译器仍然可以自由地重新排序评估。只要您的赋值和乘法运算没有明显的副作用,您的代码就可以重新排序。
但是,当您使用指针或引用时,问题就更多了。一般来说,编译器无法判断A
、B
和C
指向不同的内存区域,因此它必须假设一个赋值到 A
可能会更改以后使用的 B
或 C
值之一。因此它不能重新排序评估。在 C 中,您可以使用 restrict
告诉编译器它们不重叠,但标准 C++ 中不存在此类功能。 (如果它们是数组,这不是问题,在这种情况下,编译器知道它们不重叠。)
关于c++ - 放宽执行顺序规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9535243/