繁体   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