在浩瀚的网络中,我发现了一个有些“奇怪”的语言构造应用。这是我自己勾画的一个小例子,只是来自一个“模式”:
#include <iostream>
using namespace std;
void foo(const int i) {
cout << "foo(" << i <<")" << endl;
}
int main() {
int c = 10;
switch(c&3) while((c-=4)>=0) {
foo(c); case 3:
foo(c); case 2:
foo(c); case 1:
foo(c); case 0:;
}
return 0;
}
特别是对于无知的人,我不会透露“小事”,让它成为一种阴谋)从“知道”的角度来看,我要求提供一个纯粹的实际例子-并对小事进行解释。为什么这种结构有时(或经常?)会带来利润。
这本质上是手动展开循环,称为达夫装置。现在实际上不需要了,因为现代编译器在认为合适的情况下会自己做。(他们比我们更懂得如何“认为有必要”。)
对于较旧的编译器,这是有道理的,因为它通过一次进行多次迭代(在您的情况下为 4 次)来节省循环管理。当然,需要使用奇怪的代码
switch,以便在循环长度不是展开大小的倍数的情况下正常工作。这种构造“带来了好处”,因为与相同循环的简单实现相比,它减少了程序中条件跳转的次数
假设一个简单的实现将被“一对一”地翻译成机器代码,即 将在每 10 次迭代后检查循环继续条件。一个聪明的“四次滚动”实现只检查其循环继续条件 3 次(
10 / 4四舍五入)。应该注意的是,您最终得到了一个略微“低质量”的 Duff 设备实现,它有时比经典实现多做一次检查。例如,对于一个案例,
c = 4您的代码将对循环条件进行两次检查,而经典的 Duff's Device 只会进行一次。(替换
% 4为的“先驱优化”& 3。)