关于big_endian和little_endian,大端和小端的理解

本文深入探讨了计算机系统中字节序的概念,解释了大端和小端编码的区别,并通过实例展示了如何使用特定宏来判断当前机器的字节序。文章进一步扩展到不同大小的数据类型(如8位、16位、32位、64位)下联合体的使用,以及宏在这些情况下的适用性。

假设有个这样的一段代码:

#include <stdio.h>
int main ()
{
    union u {
        char  a[4];
        int   b;
    };

    union u test;
    test.b = 1;
    printf("%x.%x.%x.%x\n", test.a[0],test.a[1],test.a[2],test.a[3]);

    return 0;
}

在不同的机器上编译运行,结果会不一样。

x86的机器采取小端编码形式:得出的结果是:1.0.0.0;

PowerPC的机器采取大端编码形式:得出的结果时:0.0.0.1;

 

从整体来说有三种编码方式,大端形式、小端形式和网络形式:

大端形式:按内存地址升序的打印结果是:0.0.0.1;

小段形式:按内存地址升序的打印结果是:1.0.0.0;

网络形式:与大端相同;

大端小端是因为不同厂家各自为营的结果,网络形式是因为需要统一,方便不同CPU架构的机器之间传输数据,最后还是采取大端形式作为标准。

那么采取一下两个宏来辩别当前是大端还是小端比较方便:

const int endian = 1;
#define is_big_endian()     ( (*(char*)&endian ) == 0 )
#define is_little_endian()  ( (*(char*)&endian ) == 1 )

定义一个整型变量endian,初始化为1;取其变量地址&endian,然后将这个地址强转(casting)为char*型的,即(char*)&endian,然后再用*去间接访问地址(char*)&endian,即*(char*)&endian,那么就相当于那个联合体test.a[0]。

因为大端的b[0] == 0,小端的b[0] == 1,所以才能这样判断,当然前提都是int是32bits的。

扩展一下,如果int不是32bits的呢?64bits,16bits,or 8bits呢?

64bits或者32bits:那么联合体改成:

union u16 {
    char a[2]; //假定char总是8bits的
    int  b;    //假设int是16bits的
};
union u64 {
    char a[8]; //假定char总是8bits的
    int  b;    //假定int是64bits的
};

去测试的话,结果还会是,大端的机器上u.a[0] == 0,小端的机器上u.a[0] == 1;所以在64bits或者16bits上,该宏是有效的。

8bits:那么联合体改成:

union u {
    char a[1]; //假定char总是8bits的
    int  b;    //假设int是8bits的
};

去测试的话,不管大端还是小端,u.a[0] == 0,难道说bits的机子上就不适合了?

NO,如果在某个机器上int是8bits的,那么可想而知,char难道还会是8bits的吗?所以上面这个假设前提就不对,所以可能的假设是在8bits的机器上,char应该变成了4bits的。

当然,也可能我这个假设也是错误的,但是随便能碰到8bits的机器吗?甭管这么多了,16bits、32bits和64bits都搞定了,就OK了

 

转载于:https://my.oschina.net/michaelyuanyuan/blog/77295

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值