簡體   English   中英

C 是否在內部使用 2 的補碼來評估 5-4 之類的無符號數算術?

[英]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的位模式是相同的(通常是0xffff0xffffffff ),這就是為什么 2 的補碼算法很受歡迎,因為您的處理器可以定義,而您的 C 編譯器可以只使用一組addsub指令,它們在執行有符號和無符號算術時同樣有效。 但是,(在今天,至少),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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM