一.数据类型
1.整形类型有
int / short / long / char (字符是以ASCII码在内存中存储的,所以把它归类在整形类型中)
其中 每一个又包含 signed(有符号) 和unsigned(无符号)俩种类型
2.浮点型
float / double
二.在内存中是如何存储
1.整形类型
在内存中整形类型都是以二进制补码的形式储存在内存中的,为什么要以反码的形式储存呢?
首先介绍二进制的原码,反码和补码:
例如:
#include<stdio.h>
int main()
{
int a = -1;
int b = 1;
int add = a + b;
printf("%d",add);
return 0;
}
我们知道int类型在内存中存储是四个字节,一个字节是八个比特位,一个比特位是一个二进制位。所以一个int类型是32个比特位
代码中a = -1
它的原码,反码,补码
10000000000000000000000000000001 //第一位的1表示符号位为符号,最后一位表示数字为1
1111111111111111111111111111111111110 //符号位不变,其他位取反
1111111111111111111111111111111111111 //取反后加一,为补码
代码中 b = 1 正数的反码补码都与原码相同
00000000000000000000000000000001 //原码
00000000000000000000000000000001 //反码
00000000000000000000000000000001 //补码
假设我们在内存中是以原码存储,我们计算add
-1的原码 10000000000000000000000000000001
1的原码 00000000000000000000000000000001
二进制相加 10000000000000000000000000000010 我们转化为十进制为 -1;(-1)+1怎么会等于-1呢?这是我们没有考虑符号位的相加会影响计算。当我们以补码的形式计算时
-1的补码 1111111111111111111111111111111111111
1的补码 00000000000000000000000000000001
二者相加时得到 100000000000000000000000000000000多出一位,但是我们内存只能保存32位,所以去掉最前面的一位即00000000000000000000000000000000的到的add为0
内存以补码的形式保存的优点在于符号位直接参与计算,而且内存输出数据时将保存的补码也直接取反加一就可以得到原码,不需要加其他的电路
上面的类型是sgined int 类型 下面介绍unsgined int 类型
由名字就可知 无符号类型 指的是二进制储存中没有符号位
例如
#include<stdio.h>
int main()
{
unsigned int a = -1;
printf("%u\n",a);
printf("%d\n",a);
return 0;
}
我们在无符号的类型中放了一个-1
你给a赋值为-1,-1的补码是11111111111111111111111111111111将它放在a中,当我们打印的时候以%u打印,以无符号打印,那么电脑读取到的11111111111111111111111111111111是一个无符号位的数,将它转为原码打印出来,我们使用计算器计算一下:
BIN二进制 DEC十进制 我们编译运行:
当我们以%d形式打印时,电脑以int类型将-1的补码翻译成原码,结果是
讲到这里,就应该理解电脑是如何存储的了。
2.浮点型在内存中存储
首先清楚float类型占4个字节即32个比特位 double类型占8个字节即64个比特位
浮点型也区分有符号和无符号类型,那么是怎么规定的呢?
国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
例如:
int main()
{
folat a = 5.5;
return 0;
}
我们将5.5转化为二进制数101.1(注:小数部分的转化方式与整数有所差异)
例如:1001010.10100 1 0 0 1 0 1 0. 1 0 1 0 0
它每一位代表的是 然后每一位相加得74.625
我们将101.1转化为标准形式
即*1.011*
即 S=0 ; M = 1.011 ; E = 2
在公式中(-1)和2还有M的整数部分的1都是一直不变的,所以内存只要保存S E 和M的小数部分
在32个字节中,第一个比特位保存S,第二到九个保存E,剩下的保存M的小数部分,如图:
例如101.1在内存中保存的是:0 00000010 00000000000000000000011
了解这些后double类型也是一样的,只有内存分配有区别,第一个比特位保存S,第二到十二保存E,最后的52个比特位保存M的小数部分。
三.大端字节序和小端字节序
当我们知道数据在内存中是如何存储的,但是当我们打开编译器调试时,打开内存窗口:
当我们&a时,内存显示01 00 00 00与上面不符合,别急这里介绍一个概念
大端字节序:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端字节序:是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中
我们的1在内存中储存的是补码0000000000000000000000000000001,在上图中地址以16进制显示出来,一个16进制数代表4个二进制数,应该是00 00 00 01,但是上图中却相反01 00 00 00储存。
当内存储存a时,开辟空间存放它的补码,开辟空间从低到高,先存放它二进制数的低位,然后存高位,这是小端字节序的存储方法,大端字节序的方法是00 00 00 01存储。俩者都没错,只是电脑的存储方式不同。
二字节序的存储方法主要取决于编译器,有的使用大端存储,有的使用小端存储。