在看《你必須知道的496個C語言問題》一書中,提到”達夫設備”這個東西,主要是下面的代碼:
register n = (count + 7) / 8; /* count > 0 assumed */
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);
}
這是個很棒的迂迴循環展開法, 由 Tom Duff 在 Lucasfilm 時所設計。它的“傳統”形態, 是用來複制多個字節。
這裏 count 個字節從 from 指向的數組複製到 to 指向的內存地址 (這是個內存映射的輸出寄存器, 這也是爲什麼它沒有被增加)。它把 swtich 語句和複製 8 個字節的循環交織在一起, 從而解決了剩餘字節的處理問題 (當 count 不是 8 的倍數時)。相信不相信, 象這樣的把 case 標誌放在嵌套在 swtich 語句內的模塊中是合法的。當他公佈這個技巧給 C 的開發者和世界時, Duff 注意到 C 的 swtich 語法, 特別是 跌落" 行爲, 一直是被爭議的, 而
這段代碼在爭論中形成了某種論據, 但我不清楚是贊成還是反對”
函數包含一個switch語句,它的case語句同時位於一個while循環體內(有一個case語句在外面)。switch內的表達式計算被八除的餘數。執行開始於while循環內的哪個位置由這個餘數決定,最終循環退出,(沒有break)。Duff’s Device這樣就簡單漂亮地解決了邊界條件的問題。順便提一下,爲什麼”case 0”標記在循環外面呢?這樣不是打破了對稱的美觀嗎?這樣做的唯一理由是爲了處理空序列。當餘數爲零,”case 0”內就需要執行一個多餘的測試來判斷空序列的可能性。總之,這是個很酷的算法。
達夫設備是一個加速循環語句的C編碼技巧。其基本思想是–減少循環測試的執行次數。
如果在一個for循環中,其中操作執行得如果足夠快(比如說,一個賦值)——那麼測試循環條件佔用了循環所用時間的很大部分。循環應該被部分解開,這樣數個操作一次完成,測試操作也做的較少。其實,是通過switch語句將要進行的連續循環操作的次數進行了預判(根據擦case語句的位置)然後依次執行,而不必每次都去進行測試條件。
在這裏Duff’s Device是個新穎的,有創造力的解決方案。這裏有一個使用該模型的一個實例:快速拷貝和填充。
Duff’s Device對效率的負面影響可能來自於代碼膨脹(一些處理器更善於處理緊湊的循環而不是大的循環)和特別的結構。優化器被做成當遇一些更加技巧性的結構時可能會不知所措從而生成比較保守的代碼。
其實達夫設備是使用switch語句來控制進入循環的位置。
下面的程序是簡單驗證達夫設備的執行:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int n;
if(argc < 2)
{
printf("Two arguments at least!\r\n");
return -1;
}
n = atoi(argv[1]);
switch(n)
{
do {
case 0:
printf("%d ",0);
case 1:
printf("%d ",1);
case 2:
printf("%d ",2);
case 3:
printf("%d ",3);
case 4:
printf("%d ",4);
}while(--n>0);
}
return 0;
}
運行結果演示:
原文出處:http://www.cnblogs.com/xkfz007/archive/2012/03/27/2420163.html