在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
大小。
答案 0 :(得分:8)
是的,class
可以有位字段成员。在C ++中,class
和struct
之间没有区别,除了默认访问级别和默认继承类型。它们都被称为类类型。如果您可以在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包含您需要的所有信息:
constant-expression应为具有大于或等于零的值的整数常量表达式。 整数常量表达式的值可能大于位字段类型的对象表示(3.9)中的位数;在这种情况下,额外的比特用作填充比特,不参与比特字段的值表示(3.9)。类对象中的比特字段的分配是实现定义的。位字段的对齐是实现定义的。比特字段被打包到一些可寻址的分配单元中。 [注意:位字段跨越某些机器上的分配单元而不是其他机器上的分配单元。在某些机器上从右到左分配位字段,在其他机器上从左到右分配。 - 后注]
强调我的
从这里我们得到bit-feild的大小至少是底层数据类型的大小,但是如果你过度分配空间那么额外的空间就变成了padding而不用于bit的值-field成员。
答案 1 :(得分: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
答案 2 :(得分:0)
作为实施质量(QoI)的问题,是的,成员的大小实际上是我所知道的所有编译器的指定大小。
如果您询问尺寸是否必须匹配(根据标准),您必须问自己如何辨别? (以标准的符合方式。)如果你不能(我认为你不能),那么在as-if规则下,编译器可以做它喜欢的事情。
有关详细信息,请参阅C++14 standard(实际上是n4296。)
的第9.6节