计算机补码存储

以下过程用8位的有符号char表示数据。

1. 计算机为什么用补码存储整数

  • 加法运行

计算机是按照二进制存储的,并且计算机只会做加法,不会减法。

 首先看下加法,例如1+1=2
     0000 0001
     0000 0001 
    ——————————
     0000 0010
 如果是1-1呢,因为计算机不会减法,会转换为1+(-1)。这就涉及到-1怎么表示了?如果用1000 0001表示-1进行如下计算
     0000 0001
     1000 0001
     —————————
     1000 0010    这个结果就表示-2,正确结果应该是0,说明这种表示方式不行,而如果增加用于减法的硬件电路代价太高。
  • 引入补码

针对该问题,伟大的计算机科学家们想到用补码的形式表示整数(内存中存储也是存的补码),正数的补码和原码一样,负数的补码的非符号位取反后加1。

 按照这个规则,-1用补码表示为1000 0001(原码)——非符号为取反——>1111 1110——加1——>1111 1111.所以1+(-1)的计算过程如下:
      0000 0001
      1111 1111
      ——————————
      10000 0000     这个结果表示0,正确。

2.-128怎么表示

大家都知道char的取值范围是-128~127,但是-128怎么表示呢?我们按照上面的补码规则推算一下:

 1 1000 0000(用9位表示的原码)——非符号位取反——>1 0111 1111——加1——>1 1000 0000(补码)
 由上可知,原码 1 1000 0000对应的补码还是自身。截断溢出的最高位后是1000 0000。
如果只8位的1000 0000,有人可能会认为是表示-0,实际是已经用0000 0000表示0了,1000 0000再表示0就重复了,那就约定表示-128,而且这样表示不会引入错误(至于之前的大佬怎么想出来的,我暂时还不清楚),例如-128+64,计算过程如下:
 1000 0000
 0100 0000
 —————————
 1100 0000 (补码形式)——减1——>1011 1111——非符号位取反——>1100 0000(原码形式,表示-64)

3.在Linux环境下,如何用gdb查看某个变量在内存中是按照补码形式存储的呢

Image Name
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...
(gdb) l
1	#include<stdio.h>
2	#include<iostream>
3	#include<pthread.h>
4	using namespace std;
5	int main()
6	{
7		int val=-10;
8		printf("val=%d\n",val);
9		return 0;
10	}
(gdb) b test.cpp:8
Breakpoint 1 at 0x1164: file test.cpp, line 8.
(gdb) r
Starting program: /mnt/hgfs/UbuntuShareSpace/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at test.cpp:8
8		printf("val=%d\n",val);
(gdb) p &val
$1 = (int *) 0x7fffffffdf9c
(gdb) x /4xb 0x7fffffffdf9c
0x7fffffffdf9c:	0xf6	0xff	0xff	0xff
(gdb) 

如上图所示:
先用命令 p 查看变量val的内存地址,为0xffff1423.
再用命令 x 查看内存存储情况
x /4xb 0xffff1423
4:表示查看4个字节的内存.
x:表示内存数据显示的格式,和C语言中的printf保持一致.
b:表示内存单位大小 ,b:1个字节,h:Halfwords(2个字节),w:Words(4个字节).
如上图,变量val在内存中存储为"ff ff ff f6" 确实是-10的补码形式.

posted @ 2024-08-10 16:32  MadAdam  阅读(88)  评论(0)    收藏  举报