迴圈展開和 Duffs 裝置

有時,直線環不能完全包含在環體內。這是因為,迴圈需要由某些語句 B 引發。然後,迭代從一些語句 A 開始,然後在迴圈之前再次跟隨 B.

do_B();
while (condition) {
    do_A();
    do_B();
}

為了避免在程式碼中重複 B 兩次出現潛在的剪下/貼上問題,可以使用 Duff 的裝置while 體的中間開始迴圈,使用 switch 語句並通過行為。

switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default:    do_B(); /* FALL THROUGH */
}

Duff 的裝置實際上是為了實現迴圈展開而發明的。想象一下將掩碼應用於記憶體塊,其中 n 是具有正值的帶符號整數型別。

do {
    *ptr++ ^= mask;
} while (--n > 0);

如果 n 總是被 4 整除,你可以輕鬆地將其展開為:

do {
    *ptr++ ^= mask;
    *ptr++ ^= mask;
    *ptr++ ^= mask;
    *ptr++ ^= mask;
} while ((n -= 4) > 0);

但是,使用 Duff 的裝置,程式碼可以遵循這種展開的習慣用法,如果 n 不能被 4 整除,它就會跳到迴圈中間的正確位置。

switch (n % 4) do {
case 0: *ptr++ ^= mask; /* FALL THROUGH */
case 3: *ptr++ ^= mask; /* FALL THROUGH */
case 2: *ptr++ ^= mask; /* FALL THROUGH */
case 1: *ptr++ ^= mask; /* FALL THROUGH */
} while ((n -= 4) > 0);

現代編譯器很少需要這種手動展開,因為編譯器的優化引擎可以代表程式設計師展開迴圈。