大端模式和小端模式

大端模式和小端模式是两个相对的概念。网络字节顺序使用的是大端模式,一般的电脑主机中的字节顺序使用的是小端模式,一些大型的IBM主机除外。

从概念上讲:

大端模式:高字节存放在低地址,低字节存放在高地址

小端模式:高字节存放在高地址,低字节存放在低地址

举个例子:一个数据0x12 34 56 78(代表的是一个16进制数据,16进制的两位表示一个字节),那么它在小端模式中的存储方式

 

0x78

0x56

0x34

0x12

                  低地址——————————————————高地址

而在大端模式下的存储方式正好相反

0x12

0x34

0x56

0x78

             低地址——————————————————高地址

再举一个例子:一个十进制的数据100;在32位系统下它的二进制表达为:00000000000000000000000001100100

 

01100100

00000000

00000000

00000000

             低地址——————————————————高地址

在大端模式下的存储方式也是相反的:

 

00000000

00000000

00000000

01100100

             低地址——————————————————高地址

上面是大端模式和小端模式的概念性解释,下面就通过几个实例具体的解释小端模式(由于是在32位的个人电脑上进行的测试,因此只能测试小端模式的结果)。测试大小端模式经常用到的就是union联合体,因为它是多个数据共享内存的。

union u_test
{
    char a[4];
    int num;
    };
int main()
{
union u_test u_ts;
memset(&u_ts,0,sizeof(u_ts));
    u_ts.num = 100;
    printf("%d\n", u_ts.a[0]);
    printf("%d\n", u_ts.a[3]);
    return 0;
}

输出结果为:

100

0

因为是小端模式,而且chara[4]数组和int型变量num共享内存。上面已经分析了100在小端模式下的存储模式:

             a[0]                       a[1]                        a[2]                          a[3]

01100100

00000000

00000000

00000000

               低地址——————————————————高地址

因此上面的输出结果是合理的。

再举一个例子:

union u_test
{
    char a[4];
    int num;
    };
int main()
{
union u_test u_ts;
memset(&u_ts,0,sizeof(u_ts));
    u_ts.num = -1;
    printf("%x\n", u_ts.num);
    printf("%d\n", u_ts.a[0]);
    printf("%d\n", u_ts.a[3]);
    return 0;
}

其输出结果是:

ffffffff

-1

-1

按照上面的分析也是合理的。

下面就举两个比较繁琐的例子:

union u_test
{
    struct s_test
    {
        char a;
        char b;
        int in2;
        }s_ts;
    int num;
    };
int main()
{
    union u_test u_ts;
    memset(&u_ts, 0,sizeof(u_ts) );
    u_ts.num = 0x12345678;
    printf("%d\n", u_ts.s_ts.in2);
    printf("%d\n", u_ts.s_ts.a);
    printf("%d\n", u_ts.s_ts.b);
    return 0;
}

输出结果为:

 0

120

86

这个时候的union的存储分布是这样的,由于struct的存在union的字节大小为8(注意字节对齐)。那么在对num赋值后它的存储分布为:

       a              b                                       in2

0x78

0x56

0x34

0x12

0x00

0x00

0x00

0x00

     低地址——————————————————高地址

如果是在union中引入位域结构体会出现什么情况呢?

union u_test
{
    struct s_test
    {
        char a:2;
        char b:3;
        char c:3;
        }s_ts;
    int num;
    };
int main()
{
    union u_test u_ts;
    memset(&u_ts, 0,sizeof(u_ts) );
    u_ts.num = 0x64;
    printf("%d\n", u_ts.s_ts.a);
    printf("%d\n", u_ts.s_ts.b);
    printf("%d\n", u_ts.s_ts.c);
    return 0;
}

其输出结果是:

0

1

3


那么该union的存储分布为:

      c               b               a 

011

001

00

0x00

0x00

0x00

  低地址——————————————————高地址

但为什么这里的位域结构体中的存储分布顺序和结构体中的存储分布顺序不同呢?

而且对上面的例子稍作修改:

即令:u_ts.num = 0x34;

输出结果为:

0

-3

1

其中存储的分布为:

         c            b               a

001

101

00

0x00

0x00

0x00

 低地址——————————————————高地址

那么再对上面例子做下更改:

令:  u_ts.num = 0x12;

输出结果为:

-2

-4

0

         c            b              a

000

100

10

0x00

0x00

0x00

低地址——————————————————高地址

是不是这可以这样理解:对于位域结构体中某个位域如果它的首位为1,那么它转换为十进制输出的值就为负的;如果首位为0,那么它转换为十进制输出的值就是正的。而且按补码的分析,正好能得到测试出来的结果。

 

 

上面有不正确的地方,希望大家指正出来。里面有些我也弄不懂,希望大家能给些解释。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值