運算結果存儲在哪裡,由編譯器根據目標架構、優化等級、上下文動態決定,C 標準從未規定「三目運算符結果必須在寄存器」。
| 因素 | 影響 |
|---|---|
| 目標架構 | x86 偏好棧/寄存器混合,ARM/RISC-V 偏好寄存器 |
| 優化等級 | -O0 全棧,-O2/-O3 盡量寄存器,-Os 平衡代碼大小 |
| 變量生命周期 | 臨時值常在寄存器,需取地址/跨函數調用則溢出到棧 |
| 寄存器壓力 | 寄存器不足時自動溢出到棧 |
| 調試信息 | -g 可能強制內存存儲以便調試器觀察 |
// 源碼
int ternary(int a, int b) {
return a > b ? a : b;
}
// 編譯輸出 (gcc -O2 -S)
ternary:
cmp edi, esi
cmovg eax, edi # 條件移動指令,結果直接在寄存器 eax
cmovle eax, esi
ret
此處三目運算結果全程在寄存器,無內存訪問。
// 源碼
int *ptr_ternary(int a, int b) {
int result = a > b ? a : b;
return &result; // ❌ 返回局部變量地址,未定義行為,但演示存儲位置
}
// 編譯輸出
ptr_ternary:
sub rsp, 16
cmp edi, esi
cmovg eax, edi
cmovle eax, esi
mov DWORD PTR [rsp+4], eax # 強制溢出到棧,以便取地址
lea rax, [rsp+4]
add rsp, 16
ret
| 表達式類型 | 典型存儲 | 備註 |
|---|---|---|
| 常量表達式 | 編譯期計算,嵌入指令立即數 | 無運行時存儲 |
| 算術/邏輯運算 | 寄存器 (eax/rax 等) | 優化後常無內存操作 |
| 函數調用返回值 | 約定寄存器 (x86-64: rax) | ABI 規定 |
| 賦值表達式 | 目標內存位置 (棧/堆/全局) | 左值決定存儲 |
| 三目運算符 | 寄存器或棧 | 視上下文而定 |
# 生成彙編查看
gcc -O2 -S test.c -o test.s
# 或
clang -O2 -S -emit-llvm test.c -o test.ll # LLVM IR 更清晰
**語言標準規定語義,編譯器決定實現**。三目運算符無特殊存儲規則。現代編譯器在優化開啟時,極力將臨時值保持在寄存器,只有取地址、寄存器不足、跨調用等場景才溢出到棧。不要依賴具體存儲位置編寫代碼。