为了更好地理解编译器,特别是汇编语言,我一直在尝试一段简单的代码,其中第一个的总和N
计算数字,这应该导致N(N+1)/2
or N(N-1)/2
.
正如代码所示,有两个函数:
#include <cstdint>
// Once compiled with optimization, the generated assembly has a loop
uint64_t sum1( uint64_t n ) {
uint64_t sum = 0;
for ( uint64_t j=0; j<=n; ++j ) {
sum += j;
}
return sum;
}
// Once compiled with optimization, the generated assembly of the following has no loop
uint64_t sum2( uint64_t n ) {
uint64_t sum = 0;
for ( uint64_t j=0; j<n; ++j ) {
sum += j;
}
return sum;
}
在第一个函数中我循环O to N i.e. j<=n
在第二个函数中我从O to N-1 i.e. j<n
.
我的理解/观察:
-
对于第一个函数sum1
生成的程序集有一个循环 while 用于第二个函数sum2
该组件显示没有循环。但是,一旦我删除编译器优化,即-O3
,然后您终于可以在汇编中看到第二个函数的循环。
-
要查看经过编译器优化生成的程序集,请参阅此优化 https://godbolt.org/z/8z8n5bKb7.
-
要查看未经编译器优化生成的程序集,请参阅此未优化 https://godbolt.org/z/4bx8GadYP.
-
编译器是x86-64 clang
Question: 为什么编译器优化不显示程序集中的其他循环?
这是因为你的编译器非常非常聪明,它知道从 0 到 n 的所有值的总和可以用一个简单的数学公式来计算,而不是循环。
然而,你的 C++ 编译器也发现这个数学公式不能用在<=
版本,因为对于某些输入值,会触发错误,从而导致无限循环,因此所有的赌注都会被取消,并且编译器会完全按照给定的方式编译代码。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)