位域
定义结构体时,有时会使用位域来定义变量,这样能够最大限度的节省内存空间。我们知道,一个字节占8
位。如不使用位域定义,我们一般定义变量为:
U8 addr;
这个变量占8
位字节。取值范围为0-255
,可如果我们定义的变量,取值范围达不到255
的级别,那么8
位的字节中许多bit
位就浪费掉了。不要小看这几个bit
位,在嵌入式系统中,尤其是硬件资源紧张的情况下,每一个bit
都应该能发挥自己的作用。这就需要我们灵活使用位域来定义。
典型例子
一个典型的例子是定义开关标志量。开关量一般取值为0
或1
,因此仅用1
个bit位表示即可。这种情况可以使用位域来定义。如下
struct Flag_ST {
U8 flag1 :1;
U8 flag2 :1;
U8 flag3 :1;
U8 reserved : 5; }
按照上面的定义,三个flag变量每个都占用一位的空间,整个结构体也只占用一个字节的长度。
字节对齐 #Pragam pack()
定义位域之前,需要了解字节对齐。可使用#Pragam pack(n)
来实现。括号中的n
代表n
个字节对齐。举个例子,
假设U4
型占4
字节,也就是32
位U2
型占2
字节,也就是16
位U1
型占1
字节,也就是8
位
那么定义结构体
struct Flag_ST {
U4 flag1 ;
U2 flag2 ;
U1 flag3 ;}
则整个结构体我们计算是占用7
个字节长度。但实际计算sizeof
时会发现占用8
个字节。
这是因为系统默认4
字节对齐,而U1
和U2
由于加起来不够4
个字节,因此被放在了一个4
字节单位中,8
个字节中的最后一个字节被空了出来,也就浪费了。
如果我们在定义这个结构体之前加上
#Pragam pack(1)
让系统1
字节对齐,那么计算sizeof
时我们会发现该结构体占用7
字节内存,不会造成内存的浪费。