c 语言中的bit field 是一种节省内存的方式, 用于struct 或者 union 的成员变量的声明。基本的语法是:web
struct BF {
...
type_specifier [declarator] : constant_expression;
...
};
采用这样一种方式的好处是,咱们能够明确地指定某一个成员变量在内存中占用的空间(constant_expression bits). 好比:express
struct BitArray {
unsigned a : 1;
unsigned b : 1;
};
// sizeof(BitArray) == 4
struct BitArray2{
unsigned a;
unsigned b;
};
// sizeof(BitArray2) == 8
上面的例子能够看出,使用了Bit field, 咱们能够将相邻的变量a
和 b
紧凑的排列到一个unsigned
中。 而若是不适用Bit field, 很明显编译器将会单独为a
和 b
建立一个 unsigned
成员变量。svg
可是在使用bit field的时候,咱们发现有不少限制或者注意点,这里罗列出大部分可能会碰到的问题。spa
enum E { E1, E2, E3, E4, E5, E6 = 200 };
struct SMixture {
char a : 1, b : 1 ; //ok
E e1 : 2, e2 : 2; //ok
float f : 3 ; //compiler error
};
struct SMixture {
char a : 1; //start of first char
char b : 3; //continue in the first char
char c : 5; //start of second char
char d : 4; //start of third char
};
// sizeof(SMixture) == 3;
struct SMixture {
char c : 1;
char d : 0; //compiler error
char : 0; //okay
};
width 为0的域是特殊域,表示该0-width bit field的下一个成员的地址必须以该0-width bit field 的类型的对齐方式对齐。指针
struct SMixture {
char c : 1; //start of char
int : 0;
short d : 1; //start of short after alignment at type int boundary
};
//sizeof(SMixture) == 6;
struct SMixture2 {
char c : 1; //start of char
int : 0;
short d; //start of short after alignment at type int boundary
};
//sizeof(SMixture2) == 6
int main(){
SMixture s;
short* ps = &s.d; //compiler error
short& rs = s.d; //compiler error
return 0;
}
struct SMixture {
static char c : 1; //compiler error
};
/* from xnu/bsd/netinet/bootp.h */
/* * Bootstrap Protocol (BOOTP). RFC 951. */
/* * HISTORY * * 14 May 1992 ? at NeXT * Added correct padding to struct nextvend. This is * needed for the i386 due to alignment differences wrt * the m68k. Also adjusted the size of the array fields * because the NeXT vendor area was overflowing the bootp * packet. */
/* . . . */
struct nextvend {
u_char nv_magic[4]; /* Magic number for vendor specificity */
u_char nv_version; /* NeXT protocol version */
/* * Round the beginning * of the union to a 16 * bit boundary due to * struct/union alignment * on the m68k. */
unsigned short :0;
union {
u_char NV0[58];
struct {
u_char NV1_opcode; /* opcode - Version 1 */
u_char NV1_xid; /* transcation id */
u_char NV1_text[NVMAXTEXT]; /* text */
u_char NV1_null; /* null terminator */
} NV1;
} nv_U;
};