【问题标题】:Bitfield assignment - is it safe?位域分配——安全吗?
【发布时间】:2015-01-15 21:25:20
【问题描述】:

我有一堆属性塞在一个位域中以节省空间:

struct Flags {
    uint access : 2;
    uint status : 2;
    uint isEnabled : 1;
    uint isDeletable: 1;
    ...
};

然后我有一个静态的Flags defaultFlags,它在程序启动时被初始化。我的主要问题是在对象构造函数中 flags = defaultFlags; 是否安全,以便消除单独分配每个字段的 20 行?

另外,我想知道序列化呢?根据编译器的说法,Flags 是 4 个字节,我可以将其序列化为 32 位无符号整数并对其进行反灭菌而不会造成任何数据损坏吗?

【问题讨论】:

  • 位域的顺序未指定,所以对于序列化,您可能会遇到问题。
  • 如果您真的需要节省空间,您是否考虑过使用位掩码?
  • 所以如果我想要它便携,我应该废弃位域并使用手动位打包来代替?
  • 位掩码工作,让您完全控制订购和包装。您在这里得到的是对编译器的礼貌请求,可能会被忽略。
  • 这很奇怪,IIRC struct 成员不会被重新排序,但是当结构成员是位域时不是这种情况?

标签: c++ serialization variable-assignment bit-fields mass-assignment


【解决方案1】:

我的主要问题是 flags = defaultFlags; 是否安全在里面 对象构造器,为了消除分配的 20 行 每个字段单独?

是的。 Flags 的隐式定义的复制构造函数将适当地分配每个位域。 [class.copy]/15:

每个基本或非静态数据成员都以这种方式复制/移动 适合其类型:

  • 如果成员是一个数组,[..]
  • 如果成员 m 具有右值引用类型 T&& [..]
  • 否则,基址或成员将直接使用x 的相应
    基址或成员进行初始化。

我可以将其序列化为 32 位无符号整数并将其除菌为 这样没有任何数据损坏?

如果您使用相同的编译程序在同一台机器上写入和读取文件,是的。尽管其他编译器或架构上的布局可能有所不同,但该标准并未在这方面施加任何固定要求。 [class.bit]/1:

类对象中位域的分配是 实现定义。位域的对齐是 实现定义。位域被打包成一些可寻址的 分配单位。 [ 注意: 位域跨越分配单元 一些机器,而不是其他机器。位域从右到左分配 在某些机器上,在其他机器上从左到右。 ——结束注释 ]

如果您将其写入大小为sizeof Fieldchar 数组,则将其写入文件并再次从那里提取它,将其复制回Field 对象因此应该为您提供相同的值。 [basic.types]/2(强调我的):

对于平凡的任何对象(基类子对象除外) 可复制类型T,对象是否持有类型的有效值 T,构成对象的底层字节(1.7)可以复制 到charunsigned char 的数组中。如果内容 charunsigned char 的数组被复制回对象中, 对象随后应保持其原始值。

但是,正如 cmets 中所指出的,使用位掩码可以实现完全的可移植性(和合理的效率)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 2015-05-26
    • 1970-01-01
    相关资源
    最近更新 更多