c语言进阶--数据在内存中的存储

之前我们把所有的c语言的基础知识梳理了一遍,变量类型、常量变量、循环语句、选择语句、函数、数组、指针、结构体、字符串以及转义字符、操作符,进阶部分主要包括数据在内存中的存储、指针的进阶、字符串、结构体(自定义类型)以及动态内存管理。

首先我们先了解一下数据在内存中的存储,之前在学操作符时我们学习过整型提升和算术转换,与这里关系紧密,都是数据放进内存和拿出内存时应该考虑的底层造成的因素。回忆一下整型提升,char与short类型的变量在参与表达式运算的时候会整型提升为32位,算数转换就是依次向上转换。

1、数据类型包括内置类型,如char、short、int、long、long long、float、double等,自定义类型包括数组、结构体、联合体、枚举等;

2、整形在内存中的存储:整数可以用char、short、int、long、long long来存储,不同大小的整数用不同的类型来存储,可以最大化的保证内存空间的使用率。

首先是整数存放进内存:是以补码的形式存进去的,正数的原反补码都是原码,负数的补码是原码取反加一,例如将3放入变量char c中,3的补码表示为00000000000000000000000000000011,截断后8位存入c中,将3存入int c中就会直接存进去不会发生截断了,存入的原理就是如此。当我们存入的数字不符合变量的类型时就会发生意外情况(例如:我们都知道char能正常存储的范围是-128---127,那我们想将128存入char c当中,再以%d的形式读取出来会有什么结果?128的补码为00000000000000000000000010000000,截断后8位10000000,读取的时候首先整型提升为11111111111111111111111110000000,补码为10000000000000000000000010000000,读取出来就是-128,也就是存进去无论多大的数,经过截断然后按照整数的方式取出来,都是在0--127---128---1--0这个圆形之间转圈)

其次是整数从内存中拿出来,有时char或short以%d的形式拿出来就会进行整型提升,整型提升的时候一定要以char或short的类型整型提升,若是有符号的char则提升的全是符号位,若是无符号的char则提升时一定是0,一定不要看最后的打印形式来整型提升,比如将128存到char c中,并以%u的形式打印出来,128的补码为00000000000000000000000010000000,截断为10000000,整型提升为11111111111111111111111110000000(因为char的类型是有符号的char),然后直接看作无符号数打印即可得到一个很大很大的数。

一个char类型大小为1个字节,有8个bit位,能存2^8个数字,即-128--127或0-255这两种情况,这就是有符号和无符号的区别,同一个补码在内存中,以有符号数读取或是以无符号数读取结果完全不同。

大小端的定义:当我们一个变量有多个字节时就需要注意,我们存放进来的数据以什么顺序分别存放在这些字节当中,例如将3存放在int类型的变量中,3的补码是00000000000000000000000000000011,写成十六进制即为0x 00 00 00 03,我们将每个字节隔开来写,方便存入到内存的内存单元当中,03为数字的低位。以字节为单位,将数字的低位存入内存的低地址中,高位放在高地址中,这就是小端;以字节为单位,将数字的高位放在低地址中,将低位放在高地址中,这就是大端。

因此自己写代码时一定要做到将合适的数据放到合适的类型变量中去,并做到拿出的时候与存入的类型相对应,这样才不容易出现问题。

3、浮点数在内存中的存储:

首先浮点数的存储与读取与整形完全不同,我们有一个小数比如5.5,一定可以写为二进制的表示形式:101.1,也就是可以写为1.011*2^2*(-1)^0,比如将其存放到float类型的变量中,-1的指数也就是符号位用1位来表示(1表示负数,0表示正数),2的指数我们用8位来表示,这八位是无符号类型的,也就是能表示0-255之间的数,为了能表示负数,我们在指数原本的基础上+127然后再存放到这个unsigned char中,例如此时的2,2+127=129,129的补码为00000000000000000000000010000001,截断后为10000001,拿出来的时候再减127即可;然后就是1.011,1我们不用管,只存小数点后的011,占用23位,也就是01100000000000000000000

这就是浮点数的存储规则,例如我们将-5.5存入float类型的变量中,首先转化为二进制表示形式为-101.1,即-1.011*2^2*(-1)^1,符号位为1,2的指数为2,2+127=129,129的补码为00000000000000000000000010000001,截断存入10000001,后面23位为01100000000000000000000

那如何拿出来呢,倒过来即可,符号位大家都知道正负了,指数位我们按照无符号整数拿出来后还要-127,还有两种特殊情况,指数位全为1或全为0,全为1表示指数位很大很大,则浮点数整体表示无穷大,全为0表示指数非常小,则后面的23位在拿出来的时候前面不加1.,直接加0.即可然后指数直接等于-127。

本章将整形与浮点数在内存中的存储都搞清楚了,将变量的类型以及能存储的数值(就是有符号的十进制的整形(32位),即int)的大小容量、截断、整型提升、打印形式,数据的存入、取出都给串联在一起了,理解底层的东西方便我们遇到情况时解决问题。

你可能感兴趣的:(c语言,开发语言)