您的位置:首页 > 其它

大小端以及浮点数在内存中的存储方式

2017-07-26 01:53 399 查看
谈起大小端,主要是我们主机的字节序和网络的字节序。

现代CPU的累加器一次都能装载(至少)4字节(32位机器)即一个整数。那么这4字节在内存中排列的顺序将影响它被累加器装载成的整数的值。这就是字节序问题。

字节序分为大端字节序和小端字节序。大端字节序是指一个整数的高位字节(24-31bit)存储在内存的低地址处,低位字节(0-7bit)存储在内存的高地址处。小端字节序则是指整数的高位字节存储在内存的高地址处,而低字节存储在内存的低地址处。

现在我们的PC大多采用小端字节序,也被称主机字节序。

而在网络的传输过程中则是采用大端字节序,所以大端字节序也被称为网络字节序。

一个简单的程序用来测试机器的字节序。

#include<stdio.h>
void byte_order()
{
union
{
short value;
char union_bytes[sizeof(short)];
}test;
test.value = 0x0102;
if(test.union_bytes[0] == 1 && test.union_bytes[1] == 2)
{
printf("big endian\n");
}
else if(test.union_bytes[0] == 2 && test.union_bytes[1] == 1)
{
printf("little endian\n");
}
else
{
printf("unknown...\n");
}
}


下面谈谈浮点数在内存中的存储方式,我们知道不管是int型的变量还是float型或是char型变量在计算机内存中的存储方式都是以二进制补码的形式存储的。

学过计算机组成原理的都知道正数的反码、补码都是其本身。负数的补码为其反码加一。

来看看下面的这个程序:

int main(int argc, char *argv[])
{
int x = 12;
char *q = (char *)&x;
printf("%d\n", *q);   //打印什么?

float a=125.5;
char *p=(char *)&a;

printf("%d\n",*p);  //以下打印什么?
printf("%d\n",*(p+1));
printf("%d\n",*(p+2));
printf("%d\n",*(p+3));
return 0;
}


要想知道这个程序的打印结果,必须得知道int型和float在内存中二进制0、1的具体表现形式。。。。

根据vs2013测试以及看书得出以下:

整型变量在内存(32位)中前一位用来表示符号位(对于有符号整型),后31位全部用来表示数值。

浮点型变量是由符号位+阶码位+尾数位组成。

对于float型数据,其二进制有32位,其中符号位1位,阶码8位,尾数23位;

对于double型数据,其二进制为64位,符号位1位,阶码11位,尾数52位。

阶码:这里阶码采用移码表示,对于float型数据其规定偏置量为127,阶码有正有负,对于8位二进制,则其表示范围为-128-127,double型规定为1023,其表示范围为-1024-1023。比如对于float型数据,若阶码的真实值为2,则加上127后为129,其阶码表示形式为10000010

尾数:有效数字位,即部分二进制位(小数点后面的二进制位),因为规定M的整数部分恒为1,所以这个1就不进行存储了。

有了以上知识来分析程序中会输出什么!!

前三句代码主要是让一个char型指针指向int型变量然后打印int型变量的第一个字节的内容(低字节内容)它在内存中的存储形式为:0c 00 00 00 符合以上规则。

对于float型,

125.5二进制表示为1111101.1,由于规定尾数的整数部分恒为1,则表示为1.1111011*2^6,阶码为6,加上127为133,则表示为10000101

而对于尾数将整数部分1去掉,为1111011,在其后面补0使其位数达到23位,则为11110110000000000000000

内存中的表现形式为:

00000000 低地址

00000000

11111011

01000010 高地址

存储形式为: 00 00 fb 42

所以依次打印0、0、-5、66

解释下-5,内存中是:11111011,因为是有符号变量所以符号位为1是负数,所以其真值为符号位不变取反加一,变为:10000101化为十进制为-5.

所以一定要记住浮点数二进制存储形式,是符号位+阶码位+尾数位(针对有符号数)具体步骤: 把浮点数先化为科学计数法表示形式,如:1.1111011*2^6,然后取阶码(6)的值加上127(对于float)计算出阶码,尾数是处小数点后的位数(1111011),如果不够23位,则在后面补0至23位。最后,符号位+阶码位+尾数位就是其内存中二进制的存储形式。

博客如有错别字请见谅。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: