Kra*_*kos 28 c++ syntax struct data-structures
如果我有一个C++结构,定义一个64位数据字,如..
struct SMyDataWord
{
int Name : 40;
int Colour : 24;
};
Run Code Online (Sandbox Code Playgroud)
: 40
语法意味着什么......是否意味着前40位是为Name保留的,剩下的24位是为Color设置的?
这就是它似乎被使用的方式,但我以前没遇到它.
dir*_*tly 21
从C继承的Name
位域是40位宽,Colour
是24位宽.因此,您的结构至少有64位.在我的系统上,64位将是8个字节.
小智 10
这里sizeof
很好地展示了幕后发生的事情:
#include <iostream>
#include <climits>
struct bc_1 {
int a : 1;
int b : 1;
};
struct bc_2 {
int a : 31;
int b : 1;
};
struct bc_3 {
int a : 32;
int b : 1;
};
struct bc_4 {
int a : 31;
int b : 2;
};
struct bc_5 {
int a : 32;
int b : 32;
};
struct bc_6 {
int a : 40;
int b : 32;
};
struct bc_7 {
int a : 63;
int b : 1;
};
int main(int argc, char * argv[]) {
std::cout << "CHAR_BIT = " << CHAR_BIT;
std::cout << " => sizeof(int) = " << sizeof(int) << std::endl;
std::cout << "1, 1: " << sizeof(struct bc_1) << std::endl;
std::cout << "31, 1: " << sizeof(struct bc_2) << std::endl;
std::cout << "32, 1: " << sizeof(struct bc_3) << std::endl;
std::cout << "31, 2: " << sizeof(struct bc_4) << std::endl;
std::cout << "32, 32: " << sizeof(struct bc_5) << std::endl;
std::cout << "40, 32: " << sizeof(struct bc_6) << std::endl;
std::cout << "63, 1: " << sizeof(struct bc_7) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
接下来的内容取决于您的编译器和操作系统,也可能取决于您的硬件。在带有 gcc-7(a CHAR_BIT
= 8,32 位int
(即 64 位的一半long
)sizeof(int)
= 4)的macOS 上,这是我看到的输出:
CHAR_BIT = 8 => sizeof(int) = 4
1, 1: 4
31, 1: 4
32, 1: 8
31, 2: 8
32, 32: 8
40, 32: 12
63, 1: 8
Run Code Online (Sandbox Code Playgroud)
这告诉我们几件事情:如果int
类型的两个字段都适合一个int
(即上面示例中的 32 位),编译器只分配一个int
值的内存(bc_1
和bc_2
)。有一次,单个int
不能再容纳位域,我们添加第二个(bc_3
和bc_4
)。请注意,这bc_5
是在容量。
有趣的是,我们可以“选择”比允许的更多的位。见bc_6
。这里 g++-7 给出了警告:
bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type
int a : 40;
^~
Run Code Online (Sandbox Code Playgroud)
请注意:clang++ 更详细地解释了这一点
bitfields.cpp:30:9: warning: width of bit-field 'a' (40 bits) exceeds the width of its type; value will be truncated to 32 bits [-Wbitfield-width]
int a : 40;
^
Run Code Online (Sandbox Code Playgroud)
然而,似乎在幕后,编译器分配了另一个int
值得的内存。或者至少,它决定了正确的尺寸。我猜编译器警告我们不要访问这个内存int a = bc_6::a
(我敢打赌,int a
那只会有字段的前 32 位bc_6::a
......)。这可以通过bc_7
其总大小为两个int
s来确认,但第一个字段涵盖了其中的大部分。
最后替换int
与long
在上面的行为的例子如预期:
CHAR_BIT = 8 => sizeof(long) = 8
1, 1: 8
31, 1: 8
32, 1: 8
31, 2: 8
32, 32: 8
40, 32: 16
63, 1: 8
Run Code Online (Sandbox Code Playgroud)
这是一个位域定义.
Name是一个能够存储40位信息的整数.颜色可以存储24位.
这通常是为了在经常需要的结构中节省一些空间,或者将代码压缩到易于为CPU处理的大小(在您的情况下是64位.完全适合64位机器上的CPU寄存器).
访问位域的代码虽然会慢一点.