整形数据内存存储和取用的刨析理解

整形数据的存储:

在分享我对整形数据存储之前,给大家先说明几个概念。

二进制编码:

        在编译器中,例如20、-30、245等数字在存入给变量时,计算机or编译器都会将这些数字转化为二进制编码,而二进制编码又有原反补,计算机存储的时二进制编码里面的补码。其中二进制编码的最高权值位为符号位,在有符号二进制编码中:0为正数,1为负数;无符号二进制编码当正数计算值即可。

 大小端存储:

        在数据转化为二进制时,有高权值位和低权值位的区别,如1234就是1的权值最高,4的权值最低,以此来看待二进制编码的高低权值;内存的地址值有高低地址值的差别;小端存储便是二进制编码低权值位存放在内存的低地址处,便是小端存储;反之为大端存储。

整型提升:

        在32位操作下编码,int类型的大小为4个字节,而char,short类型的字节数分别为1、2;而在给char或者short类型进行%d打印时,会发生将1、2字节的二进制编码数据提升为4字节的二进制编码数据,在进行打印。(一个字节是八个比特位)

        其中整形提升过程是看不够4字节的二进制补码中最高权值的比特位;无符号数向最高权值位之前补0,直至补够4字节;有符号数是向最高权值位之前补最高权值数。

以上是我在接下来给大家分享的时候如果有不懂的可以看看上面的概念或者上网查查,我也会给大家举例说明,争取大家阅读完后对自己会有帮助。

计算机在对变量进行数据赋值的时候,先将数据转化为二进制补码,再将二进制补码转化为十六进制编码,存入到定义的类型变量开辟的内存空间中。(其中数据被转化为二进制数与变量没有关系)

举个例子:

int a = 10; (10在编译器中,数据类型为整形,4个字节,32个比特位)

其中 10 的二进制编码为:(有符号正数或者无符号数原反补相同)

0000 0000 0000 0000 0000 0000 0000 1010 ——原码

0000 0000 0000 0000 0000 0000 0000 1010 ——反码 

0000 0000 0000 0000 0000 0000 0000 1010 ——补码 

  0       0       0       0       0       0       0        A    ——十六进制0x0000000A

有符号负数与上述过程一样:

int b = -10;

其中 - 10 的编码为:(有符号负数的原反补遵循以下规律)

1000 0000 0000 0000 0000 0000 0000 1010 ——原码

1111  1111  1111 1111  1111  1111  1111  0101 ——反码 (对原码除符号位外按位取反)

1111  1111  1111 1111  1111  1111  1111  0110 ——补码 (对反码进行加一)

  F       F       F       F       F       F       F        6    ——十六进制0xFFFFFFF6

根据上面的例子,我们对整形数据存储就有一定的认识了,简约概括一下就是存入在定义的变量中都会将数据转化为二进制再转化为十六进制存入在开辟的变量空间中

有了上面的简单概括我们就要接触一些带有数据二进制截断问题的内容存储了

同样让大家看例子理解理解:

char a = -10;

注:其中char类型是1个字节,8个比特位,而 -10 是int类型,编码后存入char类型会发生数据截断的问题。

-10 的补码上面有,在0xfffffff6中,f6为低权值,我的存储为小端存储,char类型1个字节的变量存储只会将f6存入到a中,(在之前提到过的-10存入变量a中与a没有关系)这里就会发生前面数据的截断,前面的二进制编码则省略掉。

(这里的cc就是待存储,不用担心这个)

这样,我们就将整形存储中存入的过程就讲完了,接下来我们看看取的过程,其中也包含发生截断问题后的整型提升。取出的过程是先将变量内容的补码取出,然后判断是否有符号,再将补码转化为相应的原码(有符号负数将补码同样方式转化为原码,无符号与有符号正数原反补相同)

这里我先给大家看整形变量取用二进制编码的过程:

 同样 int a = -10;

          printf("a = %d\n",a);

其中 a 的数据从内存中取出,将二进制补码转化为原码的过程

1111  1111  1111 1111  1111  1111  1111  0110 ——补码

1111  1111  1111 1111  1111  1111  1111  0101 ——反码(对补码除符号位外按位取反)

1000 0000 0000 0000 0000 0000 0000 1010 ——原码(对反码进行加一)

原码转化为十进制便是我们得到的答案-10;

然而如果我们这样打印a的数据:printf("a = %u\n",a); 这里%u是按无符号数据类型打印

上述说明了:无符号二进制编码的原反补码相同,我们取到变量a内存的补码,因为是无符号数,所以原码与补码相同

接下来给大家介绍的是截断问题后整形提升的过程,这也是我相遇大家分享的重点:大家一定要切记,先进行整型提升,在进行读取数据!!

整型提升就是将char或short类型经过整型提升到4个字节后,按4字节打印

同样上述的例子:char  a = -10;

                             printf("a = %d\n",a);

这里我们刚才已经知道,变量a里存放的是一个字节的二进制补码1111 0110,而%d是按照整形类型打印,这里只有1个字节,不够整型类型的4个字节,发生整形提升,这里变量a的类型是有符号char类型,则整型提升,最高权值位数值为1,则整形提升后的二进制补码为:

1111  1111  1111 1111  1111  1111  1111  0110 ,转为原码,与上述步骤中相同,则读取值为-10;%u无符号打印读取值也很大。

 讲到这里,我给大家想要说的大致内容就讲完了,大家理解消化下上面的内容,下面是我给大家列举几个变形,大家根据上面的内容理解理解下面的例子:(如果不太懂的话可以拿纸写一写存储和取出的过程)

1、unsigned int a = -1;                                       2、 unsigned char a = -1;

     printf("a = %d\n",a); // -1                                        printf("a = %d\n",a); // 255

     printf("a = %u\n", a); // 4294967295                      printf("a = %u\n", a); // 255

3、(unsigned) char a = 256;                               4、char a = 255; or (char a = -1)

     printf("a = %d\n",a); // 0                                         printf("a = %d\n",a); // -1 

     printf("a = %u\n", a); // 0                                        printf("a = %u\n", a); // 4294967295 

5、char a = 128;                                                    6、char a = 257;

     printf("a = %d\n",a); // -128                                     printf("a = %d\n",a); // 1

上面如果大家没有问题的话,那恭喜大家,理解整形提升和数据截断的问题啦~~~

希望大家理解下下面的问题啊

  unsigned char a = 200;         

  unsigned char b = 100;

  unsigned char c = 0;

  c = a + b;

  printf(“%d %d”, a+b,c); // 300、44

给大家提个醒:先进行整型提升,在进行数据的运算,将数据存入变量中可能会发生截断问题,会丢失前面的比特位

到这里我给大家分享的内容就到此结束了,如果有什么问题的话希望大家留言,我看到会争取给大家解决的,灰灰~ 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值