示例:
for (int i = 0; i < a[index]; i++) {
// do stuff
}
每次都会a[index]
阅读吗?如果不是,如果有人想要更改循环中a[index]
的值,该怎么办?我自己从未见过它,但编译器是否做出了这样的假设?
如果条件是i < val-2
,那么每次都会评估吗?
答案 0 :(得分:3)
当系统不受程序其他部分的影响时,编译器将正常执行优化。因此,如果在条件参数的for
循环内进行更改,编译器将不会进行优化。
如上所述,编译器应该读取数组并在代码片段中的每次迭代之前检查它。您可以按如下方式优化代码,然后它只会读取数组一次以进行循环条件检查。
int cond = a[index];
for (int i = 0; i < cond; i++) {
// do stuff
}
答案 1 :(得分:2)
好吧,也许吧。
符合标准的编译器将生成与其相似的代码 每次都读。
如果manage.py migrate
和/或index
属于存储类array
,则每次都会对其进行重新评估。
如果不是,并且循环内容没有以可以预期修改其值的方式使用它们,则优化器可能会决定使用缓存结果。
答案 2 :(得分:1)
Co不会将表达式的结果存储在临时变量中。因此,所有表达式都在原地进行了评估。请注意,任何for
循环都可以更改为while
循环:
for ( def_or_expr1 ; expr2 ; expr3 ) {
...
}
变为:
def_or_expr1;
while ( expr2 ) {
...
cont:
expr3;
}
{p> continue
循环中的更新: for
与上面的while循环中的goto cont;
相同。即expr3
会针对每次迭代进行评估。
编译器可以基本上应用任何可以证明不会改变程序本质的优化。描述完整的细节对此来说太过分了,但总的来说,它可以(并且将会)优化:
a[index]
在循环中没有改变:在循环之前读取一次并保持在临时(例如寄存器)。a[index]
:使用新值更新temp(register),避免内存访问(以及索引计算)。为此,编译器必须假定在可见控制流之外不更改数组。这通常是正在编译的文件(包含所有包含的文件)。对于使用链接时间优化(LTO)的现代系统,这可以是整个最终程序 - 减去动态库。
请注意,这是一个非常简短的描述。实际上,C standard非常清楚地定义了程序必须如何执行,因此编译器可以优化的方式和方式。
如果更改了数组,例如中断处理程序或其他线程,则事情会变得复杂。根据您的目标,您需要从volatile
,原子操作(stdatomic.h
,从C11开始)到线程锁/互斥/ semapores /等。控制对共享资源的访问。