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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值