二进制数的三种形式-----原反补

原反补的基本概念:

1、原码:一个十进制数字直接转化成的二进制序列
反码:将原码按位取反(无符号型)
补码:补码=反码+1
2、数据范围:
无符号数 (int 类型) 0~255
有符号数 (char类型) -128~127
1 (7个01组合) 0 (7个01组合)
0000 0000(+0) vs 1000 0000 (-0)

3、二进制序列:(数据在内存中以 补码 形式存储)
正数(二进制最高位0):原码=反码=补码
负数(二进制最高位1):原码----反码(符号位不变,其余数位按位取反) ----- 补码=反码+1

例如:
10 :0000 1010 (二进制) ----- 0x0A (十六进制)
20 :0001 0100 (二进制)----- 0x14 (十六进制)
-10:1000 1010 (二进制)----- 1111 0101 (反码)------
1111 0110(补码)----- 0xF6 (十六进制)

== 规定: 1000 0000 = -128 (因为发生了截断)==

4、大小端问题:
内存访问的基本单位是字节,只要是字节,每个字节都有地址(大小)
数据按照字节为单位,可以被划分成若干部分,每一部分对应的“权值”是不同的,只要权值不同,就也有高低

权值: 比如 1 1 1 1 1 1 1 1 (二进制序列)
它的每一位分别对应权值为:
(从左往右按照位数(从0开始):二的多少次方)
2^7 … 2^0

把数据的低权值字节数据,放在了低地址字节里面,这种存放方式,就叫做小端;(小小小)
把数据的低权值字节数据,放在了高地址字节里面,这种存放方式,就叫做大端;

知识小练:

code 1:
运行时打开内存监视,便于查看二进制存储(大小端)

int a = 1;
printf("a=%d\n", *(char*)&a);

在这里插入图片描述
1 的二进制序列: 0x00 01 — 01 处于低权值
(01 存储在低地址中,故为小端存储)

code 2:

char a = -1; 
signed char b = -1;  
unsigned char c = -1; 
printf("a=%d,b=%d,c=%d", a, b, c);   

注意:打印是是以 %d 形式(十进制整数形式)

结果:在这里插入图片描述
a —char 类型
b---- signed char 有符号
c---- unsigned char 无符号

-1 == 1000 0001 (二进制)

code 3:

 char a = -128; 
 printf("%u\n", a); 

%u 表示输出无符号型十进制数
-128 == 1000 0000
1111 1111 1111 1111 1111 1111 1000 0000 232-27
char 类型占 8 个 bit 位,要以 %u 形式输出需要补够 32 bit 位(因为是负数所以补 1)
结果:2^32 -2^7
在这里插入图片描述

code 4:

char a = 128;             //1000 0000
printf("%d\n", a):       //int [-128~127]

1111 1111 1111 1111 1111 1111 1000 0000
(1000 0000 按最高位 1 进行补够 32 bit 位) -1,取反
1111 1111 1111 1111 1111 1111 0111 1111 (-1 减 1)
1000 0000 0000 0000 0000 0000 1000 0000 (取反)

所以输出结果为:-128
在这里插入图片描述

code 5:

 int i = -20;
 unsigned int j = 10;
 printf("%d\n", i + j);

1000 0000 0000 0000 0000 0000 0001 0100 -20
1111 1111 1111 1111 1111 1111 1110 1011 -20 反码
1111 1111 1111 1111 1111 1111 1110 1100 -20补码
0000 0000 0000 0000 0000 0000 0000 1010 10
(正数:原码=反码=补码)
1111 1111 1111 1111 1111 1111 1111 0110 -20+10
(补码相加)
1111 1111 1111 1111 1111 1111 1111 0101 反码=补码-1
1000 0000 0000 0000 0000 0000 0000 1010 原码
(反码取反) -10
(补码 形式存储在计算机中,给计算机识别的;而 原码 是给人看的)
结果:
在这里插入图片描述

code 6:

 unsigned int i;             
                   // i无符号数,[0-i] >=0   会形成死循环
 for (i = 9; i >= 0; i--) {
  printf("%u\n", i);
 }

%u 无符号十进制数 [0-i] >=0 会形成死循环
i 属于无符号数,[0~255]

code 7:

int main()
{
 char a[1000] = { 0 };
 int i = 0;
 for (i = 0; i < 1000; i++)
 {
  a[i] = -1 - i;
 }
 printf("%d", strlen(a));   
                  // strlen 计算字符串长度 ,遇到'\0'就停止 
 return 0;
}

a[0]=-1-0 // 1000 0001 (-1) ------ 1111 1110(反码)-----
1111 1111 (-1补码)

a[1]=-1-1 // 1111 1111 + 1111 1111 = 1 1111 1110 — 发生截断 1111 1110 (补)— 1111 1101 (反)------ 1000 0010
(-2 原码)

a[2]=-1-2 // 1111 1111 + 1111 1110 = 1 1111 1101 ----截断 1111 1101 (补码)------1111 1100(反)--------
1000 0011(-3原码)

a[127]=-1-127 //1111 1111 + 1000 0001 = 1 1000 0000 ----
截断 1000 0000 (-128补码)
[-1 ~ -128] 共128个数


a[128]=-1-128 //1111 1111 + 1000 0000 = 1 0111 1111 ----
截断 0111 1111 (127)

a[129]=-1-129 //1111 1111 + 1 0111 1111 = 10 0111 1110 ----
截断 0111 1110 (126)

a[]=0
[127 ~ 0] 共128 个数 --------- 128+128= 256 一共 256 个数据,第 a[256] = 0 不计算在内,所以结果为255
在这里插入图片描述

code 8:

unsigned char i = 0;
int main()
{
 for (i = 0; i <= 255; i++) {
  printf("hello world");
 }
 system("pause");
 return 0;
}

死循环
255+1 (0) 1111 1111 +1 = (1) 1111 1110—补码 —
0000 0010—原码

code 9:

int main()
{
 unsigned char a = 200;
 unsigned char b = 100;
 unsigned char c = 0;
 c = a + b;
 printf("%d %d", a + b, c);
 return 0;
}

c=a+b 将无符号a+b 的值赋给unsigned char 类型c
而 a+b 直接输出时候并没有赋给某个类型,%d 打印

结果:
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值