题目内容如下(此题目在原书的第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倍.