位域可以在C++中使用类吗?
Can bit fields be used in C++ classes?
在 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
尺寸。
是的,class
可以有位域成员。在 C++ 中,除了默认访问级别和默认继承类型外,class
和 struct
之间没有区别。它们都被称为 class 类型。如果您可以在 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;
};
请注意,我们必须在 class 中使用 public:
,因为默认情况下成员是私有的。
现在介绍一下 C++ 中位域的大小。 [class.bit]/1 包含您需要的所有信息:
The constant-expression shall be an integral constant expression with a value greater than or equal to zero. The value of the integral constant expression may be larger than the number of bits in the object representation (3.9) of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation (3.9) of the bit-field. Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [ Note: Bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. —end note ]
强调我的
从这里我们得到位域的大小至少是底层数据类型的大小,但是如果你过度分配 space 那么额外的 space 会变成填充并且不用于位域成员的值。
作为实施质量 (QoI) 的问题,是的,成员的大小确实是我所知道的所有编译器的指定大小。
如果您问尺寸是否必须匹配(根据标准),您必须问问自己如何判断? (以符合标准的方式。)如果你不能(我认为你不能),那么在 as-if 规则下,编译器可以做它喜欢的事。
有关详细信息,请参阅 C++14 standard(实际上是 n4296。)
的第 9.6 节
在 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
和位域的使用的评论:不允许 使用 sizeof
glvalue 指定位字段,如 [expr.sizeof]/p1
在 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
尺寸。
是的,class
可以有位域成员。在 C++ 中,除了默认访问级别和默认继承类型外,class
和 struct
之间没有区别。它们都被称为 class 类型。如果您可以在 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;
};
请注意,我们必须在 class 中使用 public:
,因为默认情况下成员是私有的。
现在介绍一下 C++ 中位域的大小。 [class.bit]/1 包含您需要的所有信息:
The constant-expression shall be an integral constant expression with a value greater than or equal to zero. The value of the integral constant expression may be larger than the number of bits in the object representation (3.9) of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation (3.9) of the bit-field. Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [ Note: Bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. —end note ]
强调我的
从这里我们得到位域的大小至少是底层数据类型的大小,但是如果你过度分配 space 那么额外的 space 会变成填充并且不用于位域成员的值。
作为实施质量 (QoI) 的问题,是的,成员的大小确实是我所知道的所有编译器的指定大小。
如果您问尺寸是否必须匹配(根据标准),您必须问问自己如何判断? (以符合标准的方式。)如果你不能(我认为你不能),那么在 as-if 规则下,编译器可以做它喜欢的事。
有关详细信息,请参阅 C++14 standard(实际上是 n4296。)
的第 9.6 节在 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
和位域的使用的评论:不允许 使用 sizeof
glvalue 指定位字段,如 [expr.sizeof]/p1