【问题标题】:How do bit fields interplay with bits padding in C++位域如何与 C++ 中的位填充相互作用
【发布时间】:2019-10-06 13:44:10
【问题描述】:

查看本题的C版here

当有填充位时,我有两个关于位域的问题。

假设我有一个定义为的结构

struct T { 
    unsigned int x: 1; 
    unsigned int y: 1;
};

Struct T 只有两个实际使用的位。

问题 1:这两位是否总是底层 unsigned int 的最低有效位?还是依赖于平台?

问题 2:那些未使用的 30 位是否总是初始化为 0? C++ 标准对此有何规定?

【问题讨论】:

    标签: c++ language-lawyer bit-fields memory-layout


    【解决方案1】:

    问题 1:这两位是否总是底层 unsigned int 的最低有效位?还是依赖于平台?

    非常依赖于平台。该标准甚至有一个注释只是为了澄清多少:

    [class.bit]

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

    您不能对位域的对象布局做出太多假设。

    问题2:那些未使用的30位总是初始化为0吗? C++ 标准对此有何规定?

    您的示例有一个简单的聚合,因此我们可以枚举可能的初始化。不指定初始化器...

    T t;
    

    ... 将default initialize 它,使成员具有不确定的价值。另一方面,如果您指定空括号...

    T t{};
    

    ...对象将是aggregate initialized,因此位字段将使用{} 本身进行初始化,并设置为零。但这仅适用于聚合的成员,即位字段。没有指定填充位采用什么值(如果有)。所以我们不能假设它们会被初始化为零。

    【讨论】:

      【解决方案2】:

      Q1:通常从低到高(即 x 为 1

      Q2:未使用位的值未定义。在某些编译器/平台上,堆栈初始化变量可能首先设置为零(可能!!),但不要指望它!堆分配的变量可以是任何东西,所以最好假设这些位是垃圾。使用隐藏在联合中的稍微不标准的匿名结构,您可以执行以下操作来确保位的值:

      union T {
       unsigned intval;
       struct { 
         unsigned x : 1;
         unsigned y : 1;
       };
      }; 
      
      T foo;
      foo.intval = 0;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 2018-05-11
        • 2012-08-11
        • 1970-01-01
        • 2015-02-06
        • 2019-10-30
        • 2012-04-19
        相关资源
        最近更新 更多