【发布时间】:2017-05-14 22:09:37
【问题描述】:
我了解了 2's Complement 以及 unsigned 和 signed int。所以我决定测试我的知识,据我所知,负数以2's complement 的方式存储,这样加法和减法就不会有不同的算法和电路。
如果我现在写
int main()
{
int a = -1 ;
unsigned int b = - 1 ;
printf("%d %u \n %d %u" , a ,a , b, b);
}
输出为 -1 4294967295 -1 4294967295 。现在,我查看了位模式和各种东西,然后我意识到 2 的补码中的 -1 是 11111111 11111111 11111111 11111111 ,所以当我使用 %d 解释它时,它给出了 -1 ,但是当我使用 %u 解释时,它将它视为一个正数,因此它给出4294967295。我检查了汇编的代码是
.LC0:
.string "%d %u \n %d %u"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], -1
mov DWORD PTR [rbp-8], -1
mov esi, DWORD PTR [rbp-8]
mov ecx, DWORD PTR [rbp-8]
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-4]
mov r8d, esi
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
现在-1 在 unsigned 和 signed 中都被移到了寄存器中。我想知道如果重新解释只是重要的,那么为什么我们有两种类型 unsigned 和 signed ,它是 printf 格式字符串 %d 和 %u 这很重要?
当我将负数分配给无符号整数时真正发生了什么(我了解到初始化程序将此值从int 转换为unsigned int。)但在汇编代码中我没有看到这样的事情。那么到底发生了什么??
Machine 如何知道何时必须执行2's complement,何时不执行,它是否看到负号并执行2's complement?
我已经阅读了几乎所有您认为这个问题与 重复的问题和答案,但我找不到令人满意的解决方案。
【问题讨论】:
-
“Machine 如何知道何时必须进行 2 的补码,何时不需要” - 我不明白 - 一切都归结为编程中的二进制。机器指令不关心
signed或unsigned这些是更高级别的构造。 -
@UnholySheep 我的意思是当我写 signed int a = -1 时,它被存储为 2 的补码,所以每个负数无论是否以这种方式存储在哪里?
-
对于C语言,负数可以是三种表示之一,所以不一定是2的补码。 printf 格式也必须与输入匹配,否则您的程序格式不正确。当前的 C 标准支持 2 的补码,即在有符号类型与无符号类型之间的转换不会改变本机 2 的补码计算机上的位表示。当变量在寄存器中时,机器真的不知道变量的符号性。编译器知道,程序也知道,这就够了。
-
@EOF 我很好地提出了这个问题,但人们仍然来投反对票,甚至没有告诉 OP 一旦他们的问题出了什么问题,
标签: c assembly unsigned unsigned-integer conceptual