用工具觀察 const 與 #define 的基本差異

4674 단어 c
對於 對於 對於 const 還 是 是 是 #define 來 定義 常 常 數 值, 我 想 你 可以 可以 許多 討論 討論 討論 討論 討論, 這 篇 文章 並不 並不 是 要 來下 定論, 而 是 透過 透過 編譯器 編譯器 編譯器 輸出 輸出 的 組合 語言 語言 語言 來下 來下 差別 差別 差別 差別 差別 差別 差別 差別 差別 差別 差別 差別 是以下的比較是以 GCC 預設的選項編譯, 沒有加上特都別的最佳化選項.

사용 #define



以下是一個簡單的C程式:

#define a 10
int b;

int main(void) {
    b = a;
}


接著我們使用 Compiler Explorer 觀察編譯器的組合語言輸出結果如下:



這個 這個 很 工具 工具, 可以 讓 你 你 對照 左邊 左邊 原始碼 觀察 右 邊 邊 編譯器 編譯器 輸出 的 的 組合 語言 語言 語言 語言 將 游標 移 移 到 原始檔 的 的 某 一行 一行 一行 一行 一行 會 會 以 以 以 深藍色 標示 對 應該 行 的 的 組合 組合 語言 語言 上圖 上圖 上圖 上圖 上圖 上圖右邊深藍色區域顯示的就是對應左邊 b = a 這一行的組合語言.如果你對於 x86 的組合語言沒有概念, 可以參考1. 6597

以下 以下 以下 右邊 是 內 內 的 組合 語言 語言 (我 顯示 的 的 是 是 這篇簡介, 如果 你 你 比較 習慣 看 看 看 格式 格式 的 語法, 可以 把 右邊 右邊 窗格 上方 的 -masm=att 刪除 或是 改為 -masm=intel) :

b:
        .zero   4
main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $10, b(%rip)
        movl    $0, %eax
        popq    %rbp
        ret


你 你 你 看到 可以 #define 會 在 在 編譯 編譯 前 進行 替換 替換, 實際上 並不 會 定義 變數 變數, 所以 在 在 程式 程式 開頭 開頭 只 會 看到 變數 b 被 定義 為 4 位元組 的 0. 而 對應 b = a.的組合語言是這行:

        movl    $10, b(%rip)


10 搬入 b 所在的位址.

ATT 格式的語法 사용 const



我們把一樣的程式改成使用const :

const int a = 10;
int b;

int main(void) {
    b = a;
}


同樣採用 觀察編譯器輸出的組合語言結果如下:

Compiler Explorer

以下就是右邊窗格的內容:

a:
        .long   10
b:
        .zero   4
main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $10, %eax
        movl    %eax, b(%rip)
        movl    $0, %eax
        popq    %rbp
        ret


你 你 發現 發現 會 const 會 定義 變數 變數 變數, 所以 程式 一 一 開頭 可以 看到 看到 變數 a, 並且 數值 數值 是 10. 而 到 到 b = a 這 一 行 的 的 的 組合 語言 變成 變成 這樣 這樣 :

        movl    $10, %eax
        movl    %eax, b(%rip)


第一 第一 第一 特別 個 地方 是, 因為 aconst, 所以 它 的 的 值 不 變 變 變, 因此 實際上 產生 產生 的 組合 語言 語言 根本 不 會 到 a 所在 的 位址 取值, 而 直接 直接 直接 使用 使用 使用$10 .雖然如此, 實際將 10 搬到變數 b 的動作卻還是透過中介的 eax 暫存器, 由兩個指令完成.

空間與時間的差異



從 從 的 上述 上述 語言 輸 看 看, 使用 const 的 版本 版本 不但 不但 耗費 耗費 了 放置 放置 變數 a, 而且 執行 執行 時 也 也 多 了 一道 指令 指令 這 道 指令 不但 不但 會 會 佔 用 空間 放置 指令碼 指令碼 指令碼 指令碼 會耗 會耗 會耗 也 也 也 也 也 也 也 會耗 這 道 道 道현재 Debian Linux에서 GCC 10.2.1 버전을 사용 중입니다.

$ ls -l const define
-rwxr-xr-x 1 meebox meebox 16512 May  8 20:18 const
-rwxr-xr-x 1 meebox meebox 16488 May  8 20:18 define


單純 單純 這 這 就 例子 而 言, 你 可以 看到 看到 const 的 版本 比 比 比 #define 的 版本 肥 肥 了 了 24 個位 元組, 這 對於 一般 一般 電腦 上 的 無所謂 無所謂 無所謂 無所謂 無所謂 是 是 在 在 一些 嵌入式 場合 場合 使用 使用 使用 的 的 的的小晶片上, 空間與時間都錙銖必較, 可能就不會考量 const 所帶來的好處, 改用 #define 了.

透過這樣的工具, 就可以針對相同功能但不同寫法的程式觀察實際編譯後的差異, 再決定使用哪一種寫法.

좋은 웹페이지 즐겨찾기