迴圈展開和 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);
現代編譯器很少需要這種手動展開,因為編譯器的優化引擎可以代表程式設計師展開迴圈。