我想了解以下结构声明。哪一个更适合用于内存分配,为什么?在unsigned char和unsigned int的情况下,关于填充有什么需要注意的吗?
struct data{
unsigned char a:3;
unsigned char b:4;
};
并且
struct data{
unsigned int a:3;
unsigned int b:4;
};
我想了解以下结构声明。哪一个更适合用于内存分配,为什么?在unsigned char和unsigned int的情况下,关于填充有什么需要注意的吗?
struct data{
unsigned char a:3;
unsigned char b:4;
};
struct data{
unsigned int a:3;
unsigned int b:4;
};
signed int
, unsigned int
。其他类型可能支持,也可能不支持。如果实际使用的类型指示符为int或typedef名称定义为int,则是否将位域设为signed或unsigned是实现定义的。位域(bit-field)必须有一个类型,该类型可以是_Bool、signed int、unsigned int或其他实现定义的类型的限定或非限定版本。
未命名的位域结构成员用于填充以符合外部强制布局要求。带有没有声明符但只有一个冒号和一个宽度的位域声明表示一个未命名的位域。作为一个特例,宽度为0的位域结构成员表示不再将任何其他位域打包到前一个位域(如果有的话)所在的单元中。
许多编译器已经采用了“可寻址存储单元”的约定,该单元的类型与源中指定的类型相同。例如,gcc编译器不允许使用unsigned char类型的9位位域,但允许使用unsigned int类型的位域。在您的示例中,对于Pentium使用unsigned char的结构体将是1个字节大小,而使用unsigned int的结构体将是4个字节。许多编译器还采用了这样的约定:如果位域不适合,则它将不会与下一个单元重叠。但是,可以使用标准的6.7.2.1 ad 12所规定的0宽度位域来强制执行此操作。实现可以分配任何足够大以容纳位域的可寻址存储单元。如果剩余空间足够,紧随结构中另一个位域之后的位域应打包到同一单元的相邻位中。如果剩余空间不足,则未适合的位域将重叠于相邻单元或放入下一个单元中是由实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是由实现定义的。可寻址存储单元的对齐方式未指定。
如果将位域与非位域混合使用,则6.7.2.1 ad 15规定位域和非位域的可寻址单元将具有不同的地址。没有声明符但只有冒号和宽度的位域声明表示未命名的位域。作为特殊情况,宽度为0的位域结构成员表示不再将其他位域打包到先前放置的单元中。
一些体系结构的应用程序二进制接口(ABI)强制执行实现定义的选择,以确保该体系结构的不同编译器之间的互操作性。在结构对象内,非位域成员和位域所在的单元按其声明顺序递增地具有地址。经过适当转换的指向结构对象的指针指向其初始成员(或者如果该成员是位域,则指向其所在的单元),反之亦然。结构对象内可能存在未命名的填充,但不能在其开头处存在。
// Only portable bit field types are _Bool, signed int, unsigned int
// This is not portable.
struct data{
unsigned char a:3;
unsigned char b:4;
};
struct data{
unsigned int a:3;
unsigned int b:4;
};
unsigned char
。添加函数或定义以获取和设置。void data_a_set(unsigned char *data, unsigned a) {
*data = *data & ~7u | a & 7u;
}
unsigned data_a_get(unsigned char data) {
return data & 7u;
}
// or for a more generic approach
#define B_BITS_PRIOR 3 /* sum of all previous bit widths */
#define B_BITS 4
#define MASK(w,p) (((1u << (w)) - 1) << (p))
void data_b_set(unsigned char *data, unsigned b) {
*data &= ~MASK(B_BITS, B_BITS_PRIOR);
*data |= MASK(B_BITS, B_BITS_PRIOR) & (b << B_BITS_PRIOR);
}
unsigned data_b_get(unsigned char data) {
return (data & MASK(B_BITS, B_BITS_PRIOR) >> B_BITS_PRIOR;
}
unsigned
更宽的类型,需要进行小的更改以确保更宽的和和移位操作。unsigned char
包装在struct
中。struct data {
unsigned char ab;
}