简体   繁体   English

C 是否在内部使用 2 的补码来评估 5-4 之类的无符号数算术?

[英]Does C uses 2's complement internally to evaluate unsigned numbers arithmetic like 5-4?

I have C code as我有 C 代码

#include<stdio.h>

int main()
{
    unsigned int a = 5;
    unsigned int b = 4;
    printf("%u",a-b);
}

Output of above code is 1, I am thinking that C has calculated internally the result as taking 2's compliment of -4 and then using compliment arithmetic to evaluate the result.上面代码的输出是 1,我认为 C 已经在内部计算了结果,取 2 的补码为 -4,然后使用补码算法来评估结果。 Please correct me if anything I am interpreting wrong.如果我解释错误,请纠正我。 (Here, I am talking about how C actually calculates result using binary) (这里,我说的是C实际上是如何使用二进制计算结果的)

Does C uses 2's complement internally to evaluate unsigned numbers arithmetic like 5-4? C 是否在内部使用 2 的补码来评估 5-4 之类的无符号数算术?

No, for two reasons.不,有两个原因。

unsigned int a = 5, b = 4;
printf("%u",a-b);

C guarantees that arithmetic on unsigned integer types is performed modulo the size of the type. C 保证对unsigned整数类型进行算术运算以类型的大小为模。 So if you computed ba , you'd get -1 which would wrap around to UINT_MAX , which is probably either 65535 or 4294967295 on your machine.所以如果你计算ba ,你会得到 -1 ,它会环绕到UINT_MAX ,这可能是你机器上的 65535 或 4294967295 。 But if you compute ab , that's just an ordinary subtraction that doesn't overflow or underflow in any way, so the result is an uncomplicated 1 without worrying about 2's complement or modulo arithmetic or anything.但是如果你计算ab ,那只是一个普通的减法,不会以任何方式上溢或下溢,所以结果是一个简单的 1 而不用担心 2 的补码或模算术或任何东西。

If your compiler, or your CPU architecture, chooses to implement a - b as a + -b , that's their choice, but it's an implementation detail way beneath the visibility of the C Standard, or ordinary programmers like you and me, and it won't affect the observable results of a C program at all.如果您的编译器或您的 CPU 架构选择将a - b实现为a + -b ,那是他们的选择,但这是在 C 标准或像你我这样的普通程序员可见性之下的一种实现细节方式,它赢了'根本不影响 C 程序的可观察结果。

Where things get interesting, of course, is with addition and subtraction of signed quantities.当然,事情变得有趣的地方是带符号量的加法和减法。 Up above I said that under unsigned arithmetic, 4 - 5 is -1 which wraps around to UINT_MAX .上面我说在无符号算术下, 4 - 5 是 -1 ,它环绕到UINT_MAX Using signed arithmetic, of course, 4 - 5 is -1 which is -1.当然,使用有符号算术时,4 - 5 是 -1,也就是 -1。 Under 2's complement arithmetic, it Just So Happens that the bit patterns for -1 and UINT_MAX are identical (typically 0xffff or 0xffffffff ), and this is why 2's complement arithmetic is popular, because your processor gets to define, and your C compiler gets to use, just one set of add and sub instructions, that work equally well for doing signed and unsigned arithmetic.在 2 的补码算法下,恰好 -1 和UINT_MAX的位模式是相同的(通常是0xffff0xffffffff ),这就是为什么 2 的补码算法很受欢迎,因为您的处理器可以定义,而您的 C 编译器可以只使用一组addsub指令,它们在执行有符号和无符号算术时同样有效。 But (today, at least), C does not mandate 2's complement arithmetic, and that's the other reason why the answer to your original question is "no".但是,(在今天,至少),C要求2码算术运算,这是其他原因,回答你原来的问题是“不”。


But to be clear (and to go back to your question): Just about any C compiler, for just about any architecture, is going to implement a - b by emitting some kind of a sub instruction.但是要清楚(并回到您的问题):几乎任何 C 编译器,对于几乎任何架构,都将通过发出某种sub指令来实现a - b Whether the processor then chooses to implement sub as a two's complement negate-and-add, or some other kind of negate-and-add, or via dedicated bitwise subtraction-with-borrow logic, is entirely up to that processor, and it doesn't matter (and is probably invisible) as long as it always returns a mathematically appropriate result.处理器是否选择将sub实现为二进制补码求反相加,或某种其他类型的求反相加,或通过专用的按位减法借位逻辑,完全取决于该处理器,并且它不会不重要(并且可能是不可见的),只要它总是返回一个数学上合适的结果。

The arithmetic method generally whatever is most natural on the target hardware.算术方法通常是目标硬件上最自然的。 It is not defined by the C language.它不是由 C 语言定义的。

When a processor's ALU has at least int sized registers, ab will not doubt be implemented as a single SUB instruction (or whatever the target's op-code mnemonic for subtraction might be).当处理器的 ALU 至少有int大小的寄存器时, ab毫无疑问将被实现为单个SUB指令(或任何目标的减法操作码助记符)。 In the hardware logic it may well be that the logic is equivalent to a + (~b + 1) (ie 2's complement the RHS and add) - but that is a hardware logic/micro-code implementation issue, not a language or compiler behaviour.在硬件逻辑中,该逻辑很可能等同于a + (~b + 1) (即 2 的补充 RHS 并添加)-但这是硬件逻辑/微代码实现问题,而不是语言或编译器行为。

At Godbolt for GCC x86 64-bit, the statement:在 GCC x86 64 位的Godbolt 上,声明:

 unsigned int c = a - b ;

generates the following assembly code (my comments):生成以下汇编代码(我的评论):

    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

So in that sense your question is not valid - C does not do anything in particular, the processor performs the subtraction intrinsically.所以从这个意义上说,你的问题是无效的——C 没有做任何特别的事情,处理器本质上执行减法。

The C standard allows 2's, 1's and sign+magnitude arithmetic, but in practice the world has settled on 2's complement and machines that use other representations are arcane antiques that probably never had C compilers targeted for them in any case. C 标准允许2、1 和符号 + 大小算术,但实际上世界已经确定了 2 的补码,使用其他表示的机器是神秘的古董,在任何情况下都可能从未有过 C 编译器针对它们。

There are in any case moves to remove the option for anything other than 2's complement in the language: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2218.htm在任何情况下,都可以删除语言中除 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