按位定义一个结构体
struct s_DosAttributes
{
unsigned ReadOnly :1;
unsigned Hidden :1;
unsigned System :1;
unsigned VolumeID :1;
unsigned Directory :1;
unsigned Archive :1;
unsigned reserved :2;
};
这个结构共占用4个字节, ReadOnly占用Bit0, Hidden占用Bit1...reserve占用Bit7和Bit6
比如
struct s_DosAttributes st;
memset(&st, 0, sizeof(st));
st.ReadOnly = 1;
st.VolumeID = 1;
st.reserved = 3;
unsigned char c;
memcpy(&c, &st, sizeof(c));
这时c 的值是0xc9;
1、大小端的概念
计算机中是以8位一个字节为存储单位,那么一个16位的整数,也就是keil C51中的WORD,在内存中可能有两种存储顺序bug-endian和little-endian。考虑一个WORD类型的整数0x3132(0x32是低位,0x31是高位),把它赋值给一个WORD变量,那么它在内存中的存储可能有如下两种情况:
大端模式(Big-endian)
--------------------------->>>>>>>>>>内存地址增大的方向
WORD变量的地址
0x1000 0x1001
0x31 0x32
高位字节在低位字节的前面,也就是高位在内存低的一端。可以这样记住(大端,高位在前,正常的逻辑顺序)
小端模式(Littile-endian)
--------------------------->>>>>>>>>>内存地址增大的方向
WORD变量的地址
0x1000 0x1001
0x32 0x31
高位字节在低位字节的前面,也就是高位在内存低的一端。可以这样记住(小端,低位在前,正常的逻辑顺序相反)
总结:
大端模式(Big-endian):字数据的高字节存储在低地址中,低字节存放在高地址中。
小端模式(Littile-endian):字数据的低字节存储在低地址中,高字节存放在高地址中。
2、结构体和联合体存储方式
假设一个结构类型为
struct
{
TYPE1 a;
TYPE2 b;
TYPE3 c;
}
结构成员的存放方式为
--------------------------->>>>>>>>>>内存地址增大的方向
a b c
其中各类型的成员所占的存储空间和具体的类型有关,同时,还需要考虑各编译器相关的填充。
对于联合体,所有成员所占的空间为其中最大成员的空间,如果成员中有WORD类型以上的变量,大小端模式将会对变量的存储与读取产生影响。
3、位域的概念
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
如果有WORD类型的位域,如下:
struct
{
WORD len:10;
WORD res:1;
WORD is_pcm:1;
WORD pcm_slot:4
}
则各成员的存储方式为:
--------------------------->>>>>>>>>>内存地址增大的方向
pcm_slot |is_pcm|res | len |
| | | | | | | 10bit |
总结:大小端只影响具体变量的存储,如果使用位域,位域在变量中的分配和大小端无关,按正常的存储方式分配,即前面的位域成员存在地址的高位,后面的成员存放在地址的地位。