目录
整形数据的存储
原码\反码\补码
大小端字节序
浮点型存储方式
IEEE754标准
当我们在使用C语言进行编程时,肯定离不开C语言中的基本数据类型。
char //字符型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点型
double //双精度浮点型
当我们使用这些数据类型时,都是根据需要存储或操作的数据和占用空间的大小来进行判断的。
接下来我们就谈谈这些基本的数据类型在内存中是如何存放的。
int a = 10, b = -10; //a和b在内存中分别存放什么?
我们都知道,在x86平台下一个int占4个字节,也就是32个比特位,但a是10,b是-10,它们在内存中的存放显然不可能都是10的二进制,那么如何区分正数和负数?一段二进制数,如果它是有符号数,那么它的二进制位最高位来表示符号位 (0为正 1为负) 其他位表示数值位。
如10 表示为: 00000000 00000000 00000000 00001010
则-10表示为:10000000 00000000 00000000 00001010
我们都知道 10 + (-10) 结果为 0 但上面这样相加 结果很显然不为0 计算机如何解决这个问题?
原码: 直接将正负数翻译为二进制位 最高位表示符号位
反码:正数反码是本身 负数的反码是除符号位外 其他二进制位按位取反
补码:正数的补码是本身 负数的补码是反码+1
计算机内存中对整型的存储是按照补码的方式来存储的。
-10的反码: 11111111 11111111 11111111 11110101
-10的补码:11111111 11111111 11111111 11110110
10的补码: 00000000 00000000 00000000 00001010
我们用-10的补码去加上10 会发现 结果为0 由此可见 计算机内存储整数就是补码的形式。
int a = 10;//当我们存储了一个10
//int4个字节 那么内存中应该是 00000000 00000000 00000000 00001010
//十六进制表示应该是 00 00 00 0a;
但是当我们查看内存时发现:
按理说应该是 00 00 00 0a存入内存的 为什么会是0a 00 00 00呢?
由此我们引入大小端字节序的概念。
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地址中。
注意,这里是字节序 每个字节的顺序 而不是每个比特位的顺序 所以0a依旧有序 不会变成a0。
我们这里所演示的存储方式显然就是小端存储。
如何检查自己的机器是大端还是小端存储?
int a = 1;//00 00 00 01或01 00 00 00
printf("%d", *(char*)&a);
我们把一个整型的地址强制类型转换为char* 这样就可以访问第一个字节。
查看为0还是为1 为1便是小端存储 为0就是大端存储。。
我们来看看以下代码:
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
我们发现最终输出结果是:9 0.000000 1091567616 9.000000
那么为什么有些和9一致有些又不是9呢?我们就要引入浮点数存储机制的概念了。
如果E为8位(float),它的取值范围位0~255,但是我们知道科学计数法中的E是可以出现负数的。所以IEE754存入内存时E的真实值必须加上一个中间数,如果E是8位那么它的中间数就是127。
当E全为1时 或者 E全为0时 我们可以想象到 2的-127次方和2的127次方分别表示无穷小和无穷大
正负去取决于符号S。
对于之前的问题,因为int n = 9所以在内存中