【问题标题】:Can bit fields be used in C++ classes?位域可以在 C++ 类中使用吗?
【发布时间】:2016-11-17 12:40:46
【问题描述】:

在 C 结构中,可以指定另一个位长而不是默认类型的位长,如下所示:

struct MyStruct{
    int myVar : 1;    //Size of myVar is 1 bit (so it can take values 0 or 1
    int myOtherVar: 4;    //Size of myOtherVar is 4 bits (so it can take values 0 to 15)
}

这称为位域。

我的问题是是否也可以在 C++ 类中执行此操作,如下所示:

class MyClass{
    public:
        //Some methods
    private:
        int m_myAttribute : 1;
        int m_myOtherAttribute : 4;
}

我在网上搜索了这个,但我发现的所有位字段示例都使用了结构,而不是类。

我测试了这段代码,它编译得很好,但我想知道属性的大小是否真的是指定的大小,或者编译器是否只是忽略了位字段并使用了标准的int 大小。

【问题讨论】:

  • 这不会回答你的问题,但可能是相关的:stackoverflow.com/questions/3319717/…
  • 可以通过sizeof()函数查看。另外,据我所知,结构和类之间的唯一区别是,默认类变量将是 private,默认结构变量将是 public。你应该在这里阅读:[stackoverflow.com/a/7762179/1867076]
  • C++ 中的类几乎在所有方面都与结构相同。 唯一的区别是默认访问说明符(对于类 - 私有,对于结构 - 公共)
  • @Prometheus 不,我无法使用sizeof() 进行检查。 sizeof() 不适用于位域(请参阅the link that Roy T. posted

标签: c++ class bit-fields


【解决方案1】:

是的,class 可以有位域成员。在 C++ 中,classstruct 之间没有区别,除了默认访问级别和默认继承类型。它们都被称为类类型。如果您可以在struct 中做某事,那么您可以在class 中做同样的事情。由于默认访问级别不同,它们看起来会有所不同,但您会得到相同的东西。比如

struct foo
{
    int m_myAttribute : 1;
    int m_myOtherAttribute : 4;
    int m_myOtherOtherAttribute : 27;
};

相同
class bar
{
public:
    int m_myAttribute : 1;
    int m_myOtherAttribute : 4;
    int m_myOtherOtherAttribute : 27;
};

请注意,我们必须在类中使用public:,因为默认情况下成员是私有的。

现在关于 C++ 中位域的大小。 [class.bit]/1 包含您需要的所有信息:

常量表达式应该是一个整数常量表达式,其值大于或等于零。 整数常量表达式的值可能大于位域类型的对象表示(3.9)中的位数;在这种情况下,额外的位被用作填充位并且不参与位域的值表示 (3.9)。 类对象中位域的分配是实现定义的。位域的对齐是实现定义的。位域被打包到一些可寻址的分配单元中。 [注意:位域在某些机器上跨越分配单元,而不在其他机器上。位域在某些机器上从右到左分配,在其他机器上从左到右分配。 ——尾注]

强调我的

从这里我们得到位域的大小将至少是基础数据类型的大小,但是如果您过度分配空间,那么多余的空间将变成填充并且不用于位的值-现场成员。

【讨论】:

  • except for the default access level 和默认继承类型,虽然这里没有用到。
  • 当你说这两个代码相同时,你的意思是编译后的代码是严格相同的还是只是它们做同样的事情?
  • @DonaldDuck 我希望生成完全相同的代码。 classstruct 都必须遵循相同的规则,忽略访问说明符,因此编译器应该生成相同的代码。
【解决方案2】:

在 C++ 中将位域与类或结构一起使用是完全合法的。我也推荐这个问题来进一步探讨两者的异同:What are the differences between struct and class in C++?

是的,确实考虑了位大小,只要记住内存布局的大小取决于实现

class test {
  int a : 3;
  void fun() {
      // std::cout << sizeof(a); // Illegal (*)
      a = 5; // Warning! Implicit truncation from int to 3-bit bitfield yields -3 (2's complement)
  }
};

int main() {
  std::cout << sizeof(test); // ABI-dependent, might be 4 bytes
}

(*) 让我也谈谈您对使用 sizeof 和位字段的评论:不允许glvalue 上使用 sizeof指定一个位域,如[expr.sizeof]/p1

【讨论】:

    【解决方案3】:

    作为实现质量 (QoI) 的问题,是的,成员的大小实际上是我所知道的所有编译器的指定大小。

    如果您要问尺寸是否必须匹配(根据标准),您必须问自己如何判断? (以符合标准的方式。)如果你不能(我认为你不能),那么根据 as-if 规则,编译器可以做它喜欢的事情。

    更多详情,请参阅C++14 standard(实际上是 n4296)的第 9.6 节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多