问题描述
我必须编写具有特定数据格式的文件头。为简单起见,我们假设它是:
- 位[0-7]:索引a
- 位[8-9]:索引b
- 位[10-15]:索引c
它们都是简单的无符号整数。我以为我可以使用位字段来获得不错的语法。我定义了
struct Foo {
unsigned int a : 8,b : 2,c : 6;
};
但是,我得到sizeof(Foo) == 4
。为什么?我期望这里是2字节的结构。编译器是否在我的字段之间添加填充?如果我将unsigned char
用作成员类型,则大小为2个字节。
在cppreference上说:
通常将多个相邻的位字段打包在一起(尽管 此行为是实现定义的。)
这是否意味着我不能依靠打包在一起的字段?最终,我将使用memcpy
将此struct
转换为字节流并将其写入文件。那不是位域的好用吗?仅在保证将这些位打包在一起时,这才起作用。
编辑:实际的标题与GIF format相关。许多索引仅打包成几个字节。其中一些由1、2、3或更多位组成。
解决方法
从[class.bit]/1 [摘录]:
[...]类对象内的位域分配是实现定义的。位域的对齐方式是实现定义的。
并且来自[defns.impl.defined]:
实现定义的行为
行为,对于格式正确的程序构造和正确的数据, 取决于实施和每个实施文档
因此,对于可移植的实现,您不能依赖任何特定类型的行为来实现实现定义的行为。但是,如果您要为特定的平台和编译器进行开发,则可以在一定程度上依赖已记录的实现定义的行为。