一、整数的存储
补码形式:整数在内存中通常采用补码形式进行存储。补码可以将符号位和数值位统一处理,使得CPU能够通过加法器实现加法和减法运算,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
三种表示方法:整数的二进制表示方法主要有三种,即原码、反码和补码。(原码:直接将数值按照正负的形式翻译成二进制得到的就是原码。反码:将原码的符号位不变,其他位依次按位取反,就可以得到反码。补码:反码加一就得到补码。)对于有符号整数,这三种表示方法均有符号位和数值位两部分,其中0表示正数,1表示负数,剩余的位则为数值位。
不同数据类型:在C语言中,整数分为short、char和int等类型,每种类型都有其特定的存储长度(如32位或64位),但本质上都是以二进制形式存储。
接下来,我们举个例子来看看看整数在内存中的存储
#include<stdio.h>
int main()
{
char a = -1;
signed char b= -1;
unsigned char c= -1;
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
//-1的原码是10000000000000000000000000000001
// 反码是11111111111111111111111111111110
// 补码是11111111111111111111111111111111
//因为a是char类型,char类型的大小为1字节=8个比特位,所以char a里为11111111
//%d打印有符号的整数,所以我们要对a进行整型提升,char是有符号的,在a的整型提升时在高位补充符号位
//所以a变成11111111111111111111111111111111,取反加一后打印原码得-1。
//b与a方法差不多
//由以上可知unsigned char c里存的也是11111111,因为unsigned char是无符号的,所以整型提升时补0
//得到00000000000000000000000011111111,因为%d打印的是有符号的,所以此时c是正数
//正数原反补相同,打印原码就是00000000000000000000000011111111=255,
二、浮点数的存储
IEEE 754标准:浮点数在内存中的存储遵循国际标准IEEE 754,该标准定义了单精度(float)和双精度(double)浮点数的存储格式。这两种类型的浮点数都由三个部分组成:符号位S、指数位E和有效数位M。
规则:浮点数的存储规则是将一个二进制浮点数V表示成V=(-1)^S * M * 2^E的形式,其中(-1)^S表示符号位,当S=0时,V为正数;当S=1时,V为负数。
存储空间:单精度浮点数使用4个字节(32位),而双精度浮点数使用8个字节(64位)。这些字节分别用于存储符号位、指数位和有效数位。
IEEE 754标准中单精度和双精度的浮点数存储格式的主要区别在于位数和有效数位的长度。具体来说:
单精度浮点数:使用32位二进制表示,其中1位用于符号位,8位用于指数位,23位用于有效数位。
双精度浮点数:使用64位二进制表示,同样包括1位符号位,但是指数位为11位,有效数位为52位。
这种差异导致了单精度和双精度浮点数在表示范围和精度上的不同。单精度浮点数由于其较短的指数位和有效数位,适用于需要较小范围和较低精度的应用场景,而双精度浮点数则提供了更高的精度和更大的表示范围,适合于需要高精度计算的场景。
浮点数在内存中按科学计数法存储,其整数部分始终是一个隐含的“1”,这个“1”是不变的,因此对精度不会造成影响,在保存时M时。浮点数的精度由有效数的位数决定,float的精度为7位,double的精度为15位。这意味着,如果使用float类型,由于尾部只有23位有效数,所以其实际可表示的有效数字为24位;而double类型尾部则有52位有效数,因此其有效数字为53位。
浮点数取的规则
1.E不全为0或不全为1
这时,指数E的计算值减去127(或1023),得真实值,再将有效数字M前加上第一位的1。
2.E全为0
这时,指数E等于1-127(或1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
3.E全为1
这时,如果有效数字M全为0,表示 ±无穷大(正负取决于符号位S)。
#include<stdio.h>
int main()
{
int n = 9;
float* p= (float*)&n;
printf("%d\n", n);
printf("%f\n", *p);
*p = 9.0;
printf("%d\n", n);
printf("%f\n", *p);
return 0;
}
第一个和第四个很简单,我们解读一下第二个和第三个吧
第二个:根据规则二,E的真实值为-126,是一个很小的数字,且%f只能打印到小数点后6位,所以打印出来为0.000000。
第三个:9.0二进制表示为1001.0,正数部分必须为1,小数点左移三位得1.001*2^3,
所以9.0=(-1)^0*1.001*2^3,我们可以知道S=0,M=1.001,E=3(E的计算值=3+127=130)。得9.0在内存中为01000001000100000000000000000000,最高位为0,这是一个正数,所以它的原码也是这个,这个二进制数对应的就是1091567616。
完工!一起学习,有错之处欢迎指出。