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其总大小为两个ints来确认,但第一个字段涵盖了其中的大部分。
最后替换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寄存器).
访问位域的代码虽然会慢一点.