简单理解【数据截断】和【整型提升】

2024-07-16 笔记- 2

如何理解 【数据截断】 +【 整型提升】???

在这之前可以先理解一下大小端字节序存储,之前写过关于这个的一部分笔记。
大小端字节序存储

通俗一点讲,就是,数据存放不开,只能取出部分二进制位数,其余的二进制位数就丢弃掉,丢弃掉的那一部分就是截断

【 数据截断 】

在之前学习的内容中,我也知道了【整型家族】在计算机中都是按照【补码】存储的
So
截断,是对【补码】进行截断,而不是【源码】。(一定别搞错了,对于正数来说确实无所谓,因为正数的源码,反码,补码都是一样,但是对于负数来说,可就不一样了,源码和补码不一样,可千万别搞错)

下面说一下到底如何对补码进行截取,截取以后又是怎么存到对应类型的变量中去的。

1) 以 int 的数据存到 char 中为例(int –> char)
char a = -1;  //数据截断 存储
printf("%d", a);//整型提升 打印

如上代码,如果想要将 int 的 -1 存储到 char 中,相当于大的数据存到小的空间中,此时就要进行截断。

2) 那么如何进行截断呢???

先将 10 进制的数值 转换成 2 进制的,方便理解。
因为【整型家族】的类型都是以补码的形式进行存储的,所以要将源码转换成补码(正数源码、反码、补码相同)。

源码 - 10000000 00000000 00000000 00000001 
反码 - 11111111 11111111 11111111 11111110
补码 - 11111111 11111111 11111111 11111111
    			 ^                  ^
	  【	        截断		    】【 取出 】--> 11111111(补码)
3) 知道了补码以后,截断的时候截断的时候留的哪一部分,丢弃的哪部分???
  1. 首先将所需要的【低位字节】11111111取出;(最右侧的), 然后丢弃剩余的【高位字节】;
  2. 将取出的11111111存储到 int 的 a 中

在这就要注意了:

  • 如果存储到signed(有符号) char11111111的最高位就是**【符号位】,那么不具有【数值意义】,也就不会参与计算,作用只有一个,即表示正负**

  • 如果存储到unsigned(无符号) char11111111的最高位就是【数值】,具有**【数值意义】**,会参与计算。

那么这个11111111是补码,表示的什么数值???

先将补码变成源码,就能求出来了

char a = -1;种的 a:
补码 - 11111111
取反 - 10000000
+  1 - 10000001 //--> -1
4) 疑惑???截断和 大小端有关系吗???

没有关系

截断是先将数据进行截断,然后再存储到内存中的。
和大小端字节序存储没有关系,即和按照什么顺序存储到内存中没有什么关系。
截断就是丢弃掉数据的【高位字节】

【整型提升】

整型提升有

两种

  • signed 的是一种
  • unsigned 的是一种

这两种采用的方式不一样的。

1) signed char –> int (两种补法)

​ 如果【数据】的符号位是1,高位字节全部补1
​ 如果【数据】的符号位是0,高位字节全部补2

有点抽象,下面举例说明

在signed char中存储的 11111111负数
signed char a 中 a 的数据是11111111,要存到 int(int类型的数据占4字节,4 * 8bit) 中

11111111进行整型提升,才能存储到int中去,因为符号位为1,所以前面所有的高位字节全部补1
11111111 11111111 11111111 11111111

11111111111111111111111111111111
高位字节低位字节

在signed char中存储的是 00001111正数
signed char a 中 a 的数据是00001111,要存到 int(int类型的数据占4字节,4 * 8bit) 中

00001111进行整型提升,才能存储到int中去,因为符号位为0,所以前面所有的高位字节全部补0

00000000000000000000000000001111
高位字节低位字节
补码 - 11111111 11111111 11111111 11111111
取反 - 10000000 00000000 00000000 00000000
+ 1  - 10000000 00000000 00000000 00000001 --> -1
2) unsigned –> int

​ unsigned char 中,二进制数中,开头一位是具有数值意义的。
​ 【原数据】如果是无符号的,那么无论开头是1还是0,【高字节】统一都补0
​ 因为开头的二进制数,并不是戴代表的符号。

有点抽象,下面举例说明

01111111
01111111 – > 00000000 00000000 00000000 01111111

00000000000000000000000001111111
高位字节低位字节

10000000
10000000 – > 00000000 00000000 00000000 10000000

00000000000000000000000010000000
高位字节低位字节

剩下的还没学,明天再记笔记吧~
2024-07-17

下面用一个例子进行举例,再解释一遍,也为了加深自己的印象~

问题:输出的什么???

为了再一步巩固,【数据截断】和【整型提升】,下面用题来解释明白。

#include <stdio.h>
int main()
{
 char a = -1;
 signed char b = -1;
 unsigned char c = -1;
 printf("a = %d, b = %d, c = %d", a, b, c);
 return 0;
}
//-1 -1 255

这一步为【截断】

-1
源码 - 10000000 00000000 00000000 00000001 
反码 - 11111111 11111111 11111111 11111110
补码 - 11111111 11111111 11111111 11111111
 			 ^                  ^
	  【	        截断		    】【 取出 】--> 11111111(补码) - 内存中存补码

char a 为有符号,           将 11111111(补码) 存入 a 中,开头1为符号位,表示负数
signed char a 为有符号,    将 11111111(补码) 存入 b 中,开头1为符号位
unsigned char a 为无符号,  将 11111111(补码) 存入 c 中,在这计算机不认为开头1不是符号位,它具有数值意义。

这一步为【整型提升】

下方为【整型提升】以后存的数据。

char a;           
11111111 --整型提升--> 11111111 11111111 11111111 11111111(补码) - 内存中存补码(无论是补什么,第一位就是符号位)
    				 10000000 00000000 00000000 00000000(取反) - 符号位不变,其余取反
    				 10000000 00000000 00000000 00000001(+1 得到源码) - //-1
    
signed char a;    
11111111 --整型提升--> 11111111 11111111 11111111 11111111(补码) - 内存中存补码(无论是补什么,第一位就是符号位)
    				 10000000 00000000 00000000 00000000(取反)
    				 10000000 00000000 00000000 00000001(+1 得到源码) - //-1
    
unsigned char a; //  (谨记,这里存的补码就不需要转换成源码去求值了,因为对于unsigned来说,补码就是源码)
11111111 --整型提升--> 00000000 00000000 00000000 11111111(补码 == 反码  == 源码) - 内存中存补码   
    				- //255

下面是运行的具体结果
在这里插入图片描述

笔记就先记到这里吧,小白一个,可能很多地方不对哈哈,希望网友们提出错误的地方。向网友们学习。

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值