1.整形在内存中的存储
对于c语言中的整形,我们都知道它是占有4个字节,32个比特位,但是一个整形是怎么在这32个比特位中存储的呢?
首先我们需要了解原码,反码,补码的概念。在计算机的内存中,大部分数据存放的都是补码。三者的计算关系是:原码为原数值的二进制,反码为原码对应数据类型的符号位不变,其他位取反,补码为反码加1。其中正数的原反补是相同的,负数才需要进行以上的计算。为什么会存在这三个概念,这是因为计算机的cpu只有加法计算器,没有减法计算器,科学家为实现减法,就设置了这个三个概念,因为8-3可以看作8+(-3)。
了解原反补后,我们举个例子。
我在vs2022中输入以下代码
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = -10;
return 0;
}
启动调试模式,在内存窗口中找到a,b,c的内存。(这里的内存显示我设置成以16进制显示)
这是a的内存
这是b的内存
这是c的内存
根据之前的介绍,正数的原码,反码,补码是相同的。
那么10的二进制是00000000000000000000000000001010
那么16进制便是0000000a
那么20的二进制是00000000000000000000000000010100
那么16进制便是00000014
那么-10的二进制是10000000000000000000000000001010
负数的原反补是需要计算的
反码为对应类型的符号位不变,其他位取反
则反码为11111111111111111111111111110101
补码为反码加1
则补码为11111111111111111111111111110110
16进制便是fffffff6
我们不难发现好像是这样存储的,但是顺序有点问题。
这便要引入大端小端存储的概念了。
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地 址中。
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地 址中。
对于我们计算出来的补码16进制,从左到右,数据的位置变低,从左到右,地址的位置变高,而我的机器是小端存放模式,这样就造成反着放的现象。
至此我们就了解了整形是如何存放的。
2.字符型在内存中的存储
我在这里的话只是浅谈一下字符类型能存储的数字范围。
我们知道字符类型的大小是一个字节,8个比特位。那么对于无符号的字符类型,最小便是0,最大是11111111(二进制)也就是255。那么无符号字符类型能存放的数字是0~255.
那么对于有符号的字符类型呢?
我们从一段代码开始
#include <stdio.h>
#include <string.h>
int main()
{
char a[1000];
int i;
for (i = 0;i < 1000;i++)
a[i]=-1-i;
printf("%d",strlen(a));
return 0;
}
255是vs2022的运行结果。
可是为什么呢。
我们分析一下,i从0开始,那么就不断地对a数组中的元素赋值。
一开始是-1,后面是-2,然后是-3.。。。。。。
那我们来看看负数的字符类型最大能到哪。因为字符类型是一个字节大小,8个比特位,最高位存放的是符号位。
显然是11111111最小,即-127,如果这个时候再-1,就成了100000000,超出了8个比特位,那这个数是多少呢,c语言的规则中规定这个数是-128,把他截断为10000000。然后我们再-1,就成了01111111,也就是127。那接下来就减到0,也就是我们strlen结束的标志。那我们就一共在这个数组里存放了strlen能计算的-1~-128 + 127~1,也就是255个数据。
3.浮点型的内存存放
浮点型的内存存放和整形和字符型都是非常不一样的。对于一个单精度的浮点型来说,大小是4个字节,8个比特位。如何来存放这8个比特位,c语言的规则是这样规定的。
其中S为符号位(s为0则为正数,s为1则为负数),E为指数位,M为有效数字位。
如何理解?
以-5.0为例:-5.0的二进制为-101.0,相当于-1.01*2^2(10进制是10,2进制是2),那么S为1,E为2,M为1.01
双精度和单精度所不同的是,位数不同
IEEE 754对浮点数有一些特别规定:
1.前面我们可以看到M是大于1,小于2的,所以在存放M的时候,1.01的第一个1是不存的,默认是1,在读取的时候再拿出来,这样的好处是原本只能存放23个有效位,现在可以存放24个有效位。
2.对与E,一开始c语言规定它是一个无符号数,但是在科学计数法中,我们知道,E照道理来讲,是可以出现负数的,如果将它规定位无符号数,显然是缩小了浮点型数据的大小范围。所以IEEE 754就规定,E在存放是默认加上一个中间数,对于单精度而言,这个数是127,对于双精度而言,这个数是1023,在读取时便减去这个数,这样就保证了精度,还保证了在存放的时候不用去存负数。
3.对于E的取出,有三种情况:
a.E不全为0和E不全为1
这时就减去127或1023就可以得到真实值。
b.E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于 0的很小的数字。
c.E全为1
这时,M全为0,表示±无穷大。
以上就是我对于c语言中部分数据类型的浅显认知。