C語言基礎

int get(int *p) {
    int v = *p;
    if (p == NULL)
        return -1;
    return v;
}

以 gcc 啟用最佳化來編譯上方的函式時,if (p == NULL) 的判斷可能被刪除。其理由為下列何者?

  1. A先讀取了 *p,若 p 為 NULL 在那時就已是未定義行為,因此可以假設 p 不是 NULL
  2. B標準規定與 NULL 的比較永遠為偽
  3. C在最佳化時,檢查函式引數的 if 敘述被視為呼叫端的責任,全部都可以刪除
查看答案與解析

正確答案:A. 先讀取了 *p,若 p 為 NULL 在那時就已是未定義行為,因此可以假設 p 不是 NULL

若 p 為 NULL,先執行的 int v = *p; 就是參考 NULL 指標,在那時已是未定義行為。編譯器可以假設未定義行為不會發生,因此判斷既然讀得到 *p,p 就不是 NULL,而去除 p == NULL 的判斷與 return -1。以 x86-64 的 gcc 13 加上 -O2 時,函式會變成只讀取 *p 並回傳的程式碼,而在 -O0 時判斷會保留。若要讓判斷確實生效,應在讀取 *p 之前先確認 p。

  • A. 正確。參考位於判斷之前,因此推論出 p 不是 NULL。
  • B. p 為 NULL 時,與 NULL 的比較為真。這個函式的原因在於判斷之前的 *p。
  • C. 檢查引數的判斷一般不會被刪除。只有在能推論出結果固定時才會刪除。
練習這個領域 前往領域頁面

C語言基礎的其他題目

  1. C語言的標準中,關於 int 型別的大小有何規定?下列何者正確?
  2. 在嵌入式程式中,存放32位元周邊暫存器值的變數,常以 stdint.h 的 uint32_t 宣告,而不是 unsigned int。主要理由為下列何者?
  3. 執行上方含有整數除法的程式碼時的輸出,下列何者正確?
  4. 執行上方使用前置與後置 ++ 的程式碼時的輸出,下列何者正確?
  5. 執行上方在 if 敘述的條件中寫了 = 的程式碼時的輸出,下列何者正確?