您的位置:首页 > 其它

大端模式和小端模式

2013-11-20 22:21 691 查看
大端模式和小端模式是两个相对的概念。网络字节顺序使用的是大端模式,一般的电脑主机中的字节顺序使用的是小端模式,一些大型的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
因为是小端模式,而且char型a[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,那么它转换为十进制输出的值就是正的。而且按补码的分析,正好能得到测试出来的结果。

上面有不正确的地方,希望大家指正出来。里面有些我也弄不懂,希望大家能给些解释。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: