理解C++中的位字段封装
Understanding Bit Fields packing in C++
我正在努力理解位字段。以下示例出现在C++联机文档中。
#include <iostream>
struct S {
// will usually occupy 2 bytes:
// 3 bits: value of b1
// 2 bits: unused
// 6 bits: value of b2
// 2 bits: value of b3
// 3 bits: unused
unsigned char b1 : 3, : 2, b2 : 6, b3 : 2;
};
int main()
{
std::cout << sizeof(S) << 'n'; // usually prints 2
}
关于这个例子,我不明白的是,在代码上方的注释中,说b1:3之后有2个比特未使用。然后在b3:2之后,有3个比特未被使用。为什么?这不应该是无符号字符类型定义的位数吗?或者留给下一个分配单元边界的未被支持的比特的数量?
将所有字段声明打包到一行会使查看发生了什么有点困难
struct S {
unsigned char b1:3; // 3 bits - b1
unsigned char :2; // 2 bits - unused
unsigned char b2:6; // 6 bits - b2
unsigned char b3:2; // 2 bits - b3
// Total: 13 bits
}; // 3 bits - unused (implicit padding)
两个"未使用"部分是:(1(b1
之后的未命名字段,显式宽度为2位;以及(2(在结构的末尾进行填充以将其四舍五入为16位(下一个unsigned char
单元(。
我不同意您正在阅读的文档。引用C++标准"类对象中位字段的分配是由实现定义的"。
一些编译器扩展位字段。如果你做
unsigned x : 3 ;
编译器几乎可以为分配做任何它想做的事情。我有一些采用的编译器
unsigned x : 1 ;
并将其转换为32位整数(提供最佳性能(。
你所处理的材料完全是错误的。如果你想使用实际的比特,你可以:
1( 需要确切地知道编译器是如何进行布局的;或2( 使用位掩码和<lt&,|,>>运算符,用于提取值并将其插入到已知大小的整数中。
您正在处理未命名变量。这将更容易理解:
#include <iostream>
struct S {
// will usually occupy 2 bytes:
// 3 bits: value of b1
// 2 bits: unused
// 6 bits: value of b2
// 2 bits: value of b3
// 3 bits: unused
unsigned char b1 : 3;
unsigned char : 2; // How do you reference these?
unsigned char b2 : 6, b3 : 2;
};
int main()
{
std::cout << sizeof(S) << 'n'; // usually prints 2
}
http://ideone.com/6eCUB0
未命名的是没有名称的变量,因此不能以正常方式引用它们。在一天结束的时候,在你的情况下,它们只是占用了一些空间,可能会被用于填充、对齐或其他适合这个样本的原因。
如果你把所有这些比特加起来,你会得到16个,在大多数系统上正好是2个字节。顺便说一句,正如你所读到的,评论中的">通常"一词是有原因的。
相关文章:
- 将结构字段的类型展开为可变模板参数
- 将位字段导出到数组
- 为了方便起见,我应该避免公开私有字段变量吗
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 在java中读取c++字节的位字段
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 私有字段对象与私有继承?
- 声明没有默认构造函数的字段
- C++内存模型和位字段的最大序列
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 如何在QByteArray中放置和检索位字段而不会感到痛苦?
- C++ win32 如何使密码字段可选并启用复制和粘贴?
- 如何通过UDP接收QByteArray并将其解析为位字段结构?
- 仅匹配集合中的某些字段
- 结构字段名称与 GDB 中的 STL 数组冲突
- 如何使用位字段将数据从二进制文件复制到结构中?
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何在不违反封装的情况下合法访问和修改私有字段矢量和映射
- 将位字段封装得更加紧密
- 理解C++中的位字段封装