【问题标题】:Issues with C++ bitfieldsC++ 位域的问题
【发布时间】:2020-08-18 13:26:33
【问题描述】:

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

  • 位 [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 位或更多位组成。

【问题讨论】:

  • 我在你的平台上打赌sizeof(unsigned int) == 4。您的类型的大小不会小于成员类型。如果你删除你的位域,你可能会得到一个sizeof(Foo) == 12;。位域可能在这里按预期工作。
  • 如果您打算执行内存表示流式传输,则应考虑使用固定宽度类型,例如 #include <cstdint> 中的 std::uint32_tstd::uint64_t 以避免可移植性问题。
  • uint16_t 如果您想要特定尺寸,请查看这些类型
  • 请更具体。请提供minimum reproducible example 示例输入和预期输出。从这个问题中,我觉得简单的位移应该可以完成这项工作
  • 我不确定我是否理解位字段会带来什么。我以为我会牺牲一些性能来完全控制我的内存布局。如果我的结构总大小超过 4 个字节,那才值得?

标签: c++ bit-fields


【解决方案1】:

来自[class.bit]/1 [摘录]:

[...] 类对象内的位域分配是实现定义的。位域的对齐方式是实现定义的。

还有,来自[defns.impl.defined]

实现定义的行为

行为,对于格式良好的程序结构和正确的数据, 取决于实现每个实现文档

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 2023-02-08
    • 1970-01-01
    相关资源
    最近更新 更多