int main(){
unsigned long a = 5;
int b = -6;
long c = a b;
return 0;
}
我想遵循此鏈接中說明的規則,并確認我對編譯器如何發出代碼的理解a b:https :
//en.cppreference.com/w/c/language/conversion
1-b首先轉換為unsigned long:
如果無符號型別的轉換等級大于或等于有符號型別的等級,則具有有符號型別的運算元被隱式轉換為無符號型別。
所以編譯器本質上是這樣做的:
unsigned long implicit_conversion_of_b = (unsigned long) b;
2- 上述隱式轉換本身包含在以下規則中Integer conversions:
如果目標型別是無符號的,則值 2b (其中 b 是目標型別中的位數)會被重復減去或添加到源值,直到結果適合目標型別。
3- 在加法發生之前,我們最終將這些 64 位值保存在暫存器中:
a = 0x5
b = 0xfffffffffffffffa
以上是對規則的正確映射嗎?
編輯:
4- 最終結果是 an unsigned long,需要使用此規則將其轉換為long所需的 b c:
否則,如果目標型別已簽名,則行為是實作定義的(可能包括發出信號)
uj5u.com熱心網友回復:
以上是對規則的正確映射嗎?
是的。
uj5u.com熱心網友回復:
我當然不是裝配專家,但看到這里發生的事情很有趣。用 gcc 編譯-O0:
main:
// setup stack
push rbp
mov rbp, rsp
// move 5 into 8-byte offset from the stack frame.
// rbp is the stack frame pointer, offset of 8 shows long is 8
// bytes on this architecture
mov QWORD PTR [rbp-8], 5
// move -6 to 12 bytes offset from rbp (or 4 byte offset from
// last value. This tells you int is 4 bytes on this architecture.
mov DWORD PTR [rbp-12], -6
// move the int into eax register. This is a 32-bit general
// purpose register
mov eax, DWORD PTR [rbp-12]
// movsx is a "move with sign extension" instruction. rdx is a
// 64-bit register, so this is your conversion from 32 to 64
// bits, preserving the sign
movsx rdx, eax
// moves 5 to the 64-bit rax register
mov rax, QWORD PTR [rbp-8]
// performs the 64-bit add
add rax, rdx
// not using the result, so cleanup, prepare to return
// from function
mov QWORD PTR [rbp-24], rax
mov eax, 0
pop rbp
ret
此程式集是在 x64-86 上使用 gcc 11.2 生成的
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/361339.html
標籤:C
上一篇:C是否通過參考傳遞?
下一篇:C中的迭代交叉和
