[英]Does C uses 2's complement internally to evaluate unsigned numbers arithmetic like 5-4?
我有 C 代碼
#include<stdio.h>
int main()
{
unsigned int a = 5;
unsigned int b = 4;
printf("%u",a-b);
}
上面代碼的輸出是 1,我認為 C 已經在內部計算了結果,取 2 的補碼為 -4,然后使用補碼算法來評估結果。 如果我解釋錯誤,請糾正我。 (這里,我說的是C實際上是如何使用二進制計算結果的)
C 是否在內部使用 2 的補碼來評估 5-4 之類的無符號數算術?
不,有兩個原因。
unsigned int a = 5, b = 4;
printf("%u",a-b);
C 保證對unsigned
整數類型進行算術運算以類型的大小為模。 所以如果你計算ba
,你會得到 -1 ,它會環繞到UINT_MAX
,這可能是你機器上的 65535 或 4294967295 。 但是如果你計算ab
,那只是一個普通的減法,不會以任何方式上溢或下溢,所以結果是一個簡單的 1 而不用擔心 2 的補碼或模算術或任何東西。
如果您的編譯器或您的 CPU 架構選擇將a - b
實現為a + -b
,那是他們的選擇,但這是在 C 標准或像你我這樣的普通程序員可見性之下的一種實現細節方式,它贏了'根本不影響 C 程序的可觀察結果。
當然,事情變得有趣的地方是帶符號量的加法和減法。 上面我說在無符號算術下, 4 - 5 是 -1 ,它環繞到UINT_MAX
。 當然,使用有符號算術時,4 - 5 是 -1,也就是 -1。 在 2 的補碼算法下,恰好 -1 和UINT_MAX
的位模式是相同的(通常是0xffff
或0xffffffff
),這就是為什么 2 的補碼算法很受歡迎,因為您的處理器可以定義,而您的 C 編譯器可以只使用一組add
和sub
指令,它們在執行有符號和無符號算術時同樣有效。 但是,(在今天,至少),C不要求2碼算術運算,這是其他原因,回答你原來的問題是“不”。
但是要清楚(並回到您的問題):幾乎任何 C 編譯器,對於幾乎任何架構,都將通過發出某種sub
指令來實現a - b
。 處理器是否選擇將sub
實現為二進制補碼求反相加,或某種其他類型的求反相加,或通過專用的按位減法借位邏輯,完全取決於該處理器,並且它不會不重要(並且可能是不可見的),只要它總是返回一個數學上合適的結果。
算術方法通常是目標硬件上最自然的。 它不是由 C 語言定義的。
當處理器的 ALU 至少有int
大小的寄存器時, ab
毫無疑問將被實現為單個SUB
指令(或任何目標的減法操作碼助記符)。 在硬件邏輯中,該邏輯很可能等同於a + (~b + 1)
(即 2 的補充 RHS 並添加)-但這是硬件邏輯/微代碼實現問題,而不是語言或編譯器行為。
在 GCC x86 64 位的Godbolt 上,聲明:
unsigned int c = a - b ;
生成以下匯編代碼(我的評論):
mov eax, DWORD PTR [rbp-4] ; Load a to EAX
sub eax, DWORD PTR [rbp-8] ; Subtract b from EAX
mov DWORD PTR [rbp-12], eax ; Write result to c
所以從這個意義上說,你的問題是無效的——C 沒有做任何特別的事情,處理器本質上執行減法。
C 標准允許2、1 和符號 + 大小算術,但實際上世界已經確定了 2 的補碼,使用其他表示的機器是神秘的古董,在任何情況下都可能從未有過 C 編譯器針對它們。
在任何情況下,都可以刪除語言中除 2 補碼以外的任何選項: http : //www.open-std.org/jtc1/sc22/wg14/www/docs/n2218.htm
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.