[英]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.