# 达夫的设备如何工作？

``int count; // Set to 20 { int n = (count + 7) / 8; // n is now 3. (The "while" is going // to be run three times.) switch (count % 8) { // The remainder is 4 (20 modulo 8) so // jump to the case 4 case 0: // [skipped] do { // [skipped] *to = *from++; // [skipped] case 7: *to = *from++; // [skipped] case 6: *to = *from++; // [skipped] case 5: *to = *from++; // [skipped] case 4: *to = *from++; // Start here. Copy 1 byte (total 1) case 3: *to = *from++; // Copy 1 byte (total 2) case 2: *to = *from++; // Copy 1 byte (total 3) case 1: *to = *from++; // Copy 1 byte (total 4) } while (--n > 0); // N = 3 Reduce N by 1, then jump up // to the "do" if it's still } // greater than 0 (and it is) }` `

` `int count; // { int n = (count + 7) / 8; // // switch (count % 8) { // // case 0: // do { // The while jumps to here. *to = *from++; // Copy 1 byte (total 5) case 7: *to = *from++; // Copy 1 byte (total 6) case 6: *to = *from++; // Copy 1 byte (total 7) case 5: *to = *from++; // Copy 1 byte (total 8) case 4: *to = *from++; // Copy 1 byte (total 9) case 3: *to = *from++; // Copy 1 byte (total 10) case 2: *to = *from++; // Copy 1 byte (total 11) case 1: *to = *from++; // Copy 1 byte (total 12) } while (--n > 0); // N = 2 Reduce N by 1, then jump up // to the "do" if it's still } // greater than 0 (and it is) }` `

` `int count; // { int n = (count + 7) / 8; // // switch (count % 8) { // // case 0: // do { // The while jumps to here. *to = *from++; // Copy 1 byte (total 13) case 7: *to = *from++; // Copy 1 byte (total 14) case 6: *to = *from++; // Copy 1 byte (total 15) case 5: *to = *from++; // Copy 1 byte (total 16) case 4: *to = *from++; // Copy 1 byte (total 17) case 3: *to = *from++; // Copy 1 byte (total 18) case 2: *to = *from++; // Copy 1 byte (total 19) case 1: *to = *from++; // Copy 1 byte (total 20) } while (--n > 0); // N = 1 Reduce N by 1, then jump up // to the "do" if it's still } // greater than 0 (and it's not, so bail) } // continue here...` `

Dobb博士的杂志中的解释是我在这个主题上找到的最好的解释 。

` `for (i = 0; i < len; ++i) { HAL_IO_PORT = *pSource++; }` `

` `int n = len / 8; for (i = 0; i < n; ++i) { HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; HAL_IO_PORT = *pSource++; }` `

:)变成：

` `int n = (len + 8 - 1) / 8; switch (len % 8) { case 0: do { HAL_IO_PORT = *pSource++; case 7: HAL_IO_PORT = *pSource++; case 6: HAL_IO_PORT = *pSource++; case 5: HAL_IO_PORT = *pSource++; case 4: HAL_IO_PORT = *pSource++; case 3: HAL_IO_PORT = *pSource++; case 2: HAL_IO_PORT = *pSource++; case 1: HAL_IO_PORT = *pSource++; } while (--n > 0); }` `

duffs设备的重点在于减少在紧密的memcpy实现中完成的比较次数。

` ` do { *a = *b++; } while (--count > 0);` `

` `void dsend(char* to, char* from, count) { 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); } }` `

• 在语言定义中放宽switch语句的规范。 在设备发明的时候，这是“C语言程序设计语言”的第一版，它只要求开关的受控语句是一个语法上有效的（复合）语句，在这种语句中，标签可以出现在任何子语句的前面。 结合这样一个事实，如果没有中断声明，控制流程将从一个案例标签控制的声明到下一个控制的声明中，这意味着代码指定了一系列从顺序的源地址到存储器映射的输出端口。
• 合法跳到C中循环的能力

1：Duffs设备是循环展开的特殊实现。 什么是循环展开？

` `for (int i=0; i<N; i++) { // [The loop code...] }` `

` `for (int i=0; i<N/n; i++) { // [The loop code...] // [The loop code...] // [The loop code...] ... // [The loop code...] // n times! }` `

2：Duffs设备与标准循环展开有什么不同？

Duff的设备解决的问题是循环展开（如您在发布的Wiki链接中无疑会看到的那样）。 这基本上等同于运行时间效率的优化，超过内存占用。 达夫的设备处理串行复制，而不仅仅是任何老问题，而是一个经典的例子，说明如何通过减少循环中比较所需的次数来优化。

` `for(int i = 0; i < 100; i++) { myArray[i] += 1; }` `

` `for(int i = 0; i < 100; i+10) { myArray[i] += 1; myArray[i+1] += 1; myArray[i+2] += 1; myArray[i+3] += 1; myArray[i+4] += 1; myArray[i+5] += 1; myArray[i+6] += 1; myArray[i+7] += 1; myArray[i+8] += 1; myArray[i+9] += 1; }` `

` ` instruction label1: instruction instruction instruction instruction jump to label1 some condition` `

` ` evaluate expression into register r compare r with first case value branch to first case label if equal compare r with second case value branch to second case label if equal etc.... first_case_label: instruction instruction second_case_label: instruction instruction etc...` `

` `int n = (count + 1) / 8; switch (count % 8) { LOOP: case 0: if(n-- == 0) break; putchar('.'); case 7: putchar('.'); case 6: putchar('.'); case 5: putchar('.'); case 4: putchar('.'); case 3: putchar('.'); case 2: putchar('.'); case 1: putchar('.'); default: goto LOOP; }` `