編譯器

在上方函式中,編譯器無法直接進行把 *b 的讀取移到迴圈之外的最佳化,其原因為何?

void add(int *a, int *b, int n) {
    for (int i = 0; i < n; i++)
        a[i] += *b;
}
  1. A因為 *b 是整數,移到迴圈外會使值的精確度下降
  2. B因為 a 與 b 可能指向同一個位置,對 a[i] 的寫入可能會使 *b 改變
  3. C因為規定編譯器絕對不可以最佳化以指標為引數的函式
查看答案與解析

正確答案:B. 因為 a 與 b 可能指向同一個位置,對 a[i] 的寫入可能會使 *b 改變

乍看之下,*b 在迴圈中不會改變,似乎只讀一次就好。然而若呼叫端像 add(x, &x[3], n) 這樣,傳入指向 a 的某個元素的指標作為 b,對 a[3] 的寫入就會使 *b 的值改變。編譯器無法否定這種可能性(別名),所以會產生每次都重新讀取的程式碼。在C語言中,若對指標加上 restrict,保證它們指向不同的位置,就能進行最佳化。這既不是精確度的問題,也不是最佳化遭到禁止。

  • A. 移動整數的讀取並不會改變精確度。
  • B. 正確。因為 a 與 b 有重疊的可能(別名)。
  • C. 使用指標的函式同樣可以被最佳化。
練習這個領域 前往領域頁面

編譯器的其他題目

  1. 在編譯器的暫存器配置中,使用對干涉圖著色(染色)的方法時,圖中的節點與邊所代表的事物,下列組合何者正確?
  2. 在暫存器配置中發生「溢出(spill)」時,所產生的程式碼會變成怎樣?
  3. 編譯器的指令排程,其主要目的為何?
  4. 對上方函式最後的遞迴呼叫進行尾端呼叫最佳化,會有什麼效果?
  5. 關於編譯器與直譯器的差異,下列何者正確?

這個領域的比較