【问题标题】:How do bit fields interplay with bits padding in C位域如何与 C 中的位填充相互作用
【发布时间】:2019-05-20 07:36:02
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 请只问一个问题。
  • 虽然 C 和 C++ 标准可能说了类似的话,但仍可能存在差异,使得语义非常不同。
  • 使用的位的位置是实现定义的(C11 §6.7.2.1 ¶11。未使用的位是不可访问的,并且不保证初始化为任何特定值。如果对您很重要,请不要使用位-fields。几乎没有关于位域的可移植性,除了它们存在并在给定平台上工作(但它们在其他平台上存在并且工作方式不同)。
  • 郑重声明,这些不是语言律师的问题。当您必须在嵌入式平台上操作寄存器位时,这很重要。

标签: c struct bit-manipulation language-lawyer


【解决方案1】:

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

不,它依赖于系统和编译器。您永远无法假设或知道它们是 MSB 或 LSB。

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

取决于你如何初始化结构。本地范围内未初始化的结构可能在填充位/字节中包含垃圾值。使用至少一个初始化程序集初始化的结构即使在填充字节中也保证包含零:my_struct = { something };


来源

为什么上述工作有些复杂的语言律师细节。

C17 6.7.9/9(强调我的)这样说:

除非另有明确说明,为本子条款的目的,未命名 结构和联合类型对象的成员不参与初始化。 结构对象的未命名成员即使在初始化后也具有不确定的值。

这意味着我们根本无法信任填充位/字节。 但是上述规则有一个例外(第 20 节强调我的):

如果大括号括起来的列表中的初始值设定项少于元素或成员的数量 聚合,或用于初始化已知数组的字符串文字中的更少字符 大小超过数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储持续时间的对象相同。

意思是如果至少有一个初始化器,那么下面的静态存储初始化规则适用:

C17 6.7.9/10(强调我的):

如果有静态的对象或线程存储持续时间没有初始化 显式地,那么:/--/

  • 如果是聚合,则每个成员都根据这些规则(递归地)初始化,并且任何填充都被初始化为零位

【讨论】:

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