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

谈起大小端,主要是我们主机的字节序和网络的字节序。
现代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测试以及看书得出以下:

  1. 整型变量在内存(32位)中前一位用来表示符号位(对于有符号整型),后31位全部用来表示数值。
  2. 浮点型变量是由符号位+阶码位+尾数位组成。
    对于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位。最后,符号位+阶码位+尾数位就是其内存中二进制的存储形式。

    博客如有错别字请见谅。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值