C ++位域问题 实现定义的行为

问题描述

我必须编写具有特定数据格式的文件头。为简单起见,我们假设它是:

  • 位[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]

实现定义的行为

行为,对于格式正确的程序构造和正确的数据, 取决于实施每个实施文档

因此,对于可移植的实现,您不能依赖任何特定类型的行为来实现实现定义的行为。但是,如果您要为特定的平台和编译器进行开发,则可以在一定程度上依赖已记录的实现定义的行为。