题目内容如下(此题目在原书的第141页):
15. (*1.5) What does the following example do?
void send(int* to, int* from, int count) // Duff’s device. Helpful comment deliberately deleted. { int n = (count+7)/8; switch(count%8) { case 0: do{ *to++ = *from++; case 7: *to++ = *from++; case 6: *to++ = *from++; case 5: *to++ = *from++; case 4: *to++ = *from++; case 3: *to++ = *from++; case 2: *to++ = *from++; case 1: *to++ = *from++; }while(--n>0); } }
Why would anyone write something like that?
乍一看,这好像有语法错误吧?但在编译器上编译、运行正常,下面给出我的测试代码:
template<class T, size_t N> void printArray(T (&a)[N], char delimiter = ' '); int main() { int a[10] = {0}; int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; send(a, b, 4); printArray(a); cout << endl; printArray(b); cout << endl; } template<class T, size_t N> void printArray(T (&a)[N], char delimiter) { for (size_t i = 0; i < N; ++i) { cout << a[i] << delimiter; } }
程序的输出结果为:
1 2 3 4 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
函数分析:
根据程序的输出结果,大概可以猜出来程序的作用了:从数组from复制前count个整数到数组to中。
函数中的switch-case语句用以决定从do-while循环体的哪条语句开始执行。
复制的个数可用下面的公式表示(由在线方程编辑工具codecogs生成):
第一个问题回答了,那么第二个问题呢?
如果要我实现这个函数,大概会有如下的代码:
//implemented by mjn 2012/10/19 void send1(int* to, int* from, int count) { if (count < 0) return; if (count == 0) count = 8; while (count-- > 0) { *to++ = *from++; } }
duff的代码复制了若干个8组数据, 首先复制的是前8的余数个数据. 总结一下, 它有2个特点:
1) 通过switch实现goto的跳转功能, 进入到循环体的中间, 来复制8的余数个数据.
2) 将循环展开(一次复制8组), 以增加代码长度来换取执行的效率. 我写的代码中, 循环中的计数器自减操作多执行8倍, 计数器与0比较多执行8倍.
while switch-case
Duff's device神奇的switch
Duff's device at wikipedia
Description and original mail by Duff at Lysator
How does Duff's device work?
Explanation from c-faq.com