您的位置:首页 > 编程语言 > C语言/C++

《The C++ Programming Language, special edition》第6章6.6节中的一道有趣习题ch6.6-15

2012-10-05 03:15 411 查看
题目内容如下(此题目在原书的第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)
, 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)
, 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倍.

References:
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: