C ++ struct语法“a:b”是什么意思

时间:2009-05-05 10:36:36

标签: c++ data-structures syntax struct

如果我有一个C ++结构,定义一个64位数据字,如..

struct SMyDataWord
{
    int Name : 40;
    int Colour : 24;
};

: 40语法意味着什么...是否意味着前40位是为Name保留的,剩余的24位是为Color?

这就是它的使用方式,但我以前没有遇到它。

5 个答案:

答案 0 :(得分:20)

从C Name继承的位域是40位宽,Colour是24位宽。因此,您的结构至少有64位。在我的系统上,64位将是8个字节。

答案 1 :(得分:9)

是的,这是bitfields的语法。它们通常用于定义映射到硬件寄存器的结构。如果你决定使用它们,有一些事情需要记住,一个是你不知道编译器如何进行布局,组成字段的实际字节中的排序和填充可以并且将在编译器之间有所不同(也许使用相同的编译器,但也有不同的优化设置。)

答案 2 :(得分:6)

这是一个位域定义。

Name是一个能够存储40位信息的整数。颜色可以存储24位。

这通常是为了在常用结构中节省一些空间,或者将代码压缩到易于为CPU处理的大小(在您的情况下为64位。完全适合64位机器上的CPU寄存器)。

访问位域的代码虽然会慢一点。

答案 3 :(得分:3)

Use them judiciously

  

请记住几乎所有事情   位字段是实现   依赖。例如,是否位   从左到右存储或   从右到左取决于实际情况   硬件架构。此外,   每个编译器使用不同的成员   对齐模型,这就是尺寸的原因   优化的BillingRec是12   字节而不是9.你不能拿一个   位字段的地址也不能创建   位数组。最后,大多数   实现位字段的使用   引起速度开销。因此,何时   你优化你的代码,衡量   某种优化和效果   在您决定使用之前进行权衡   它

答案 4 :(得分:2)

这里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;
}

以下内容取决于您的编译器和操作系统,可能还取决于您的硬件。在具有gcc-7的macOS上(CHAR_BIT = 8,32位int(即64位long的一半)sizeof(int) = 4)这是输出我明白了:

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

这告诉我们几件事:如果int类型的两个字段都适合单个int(即上例中的32位),编译器只分配一个int& #39;值得记忆(bc_1bc_2)。一次,int只能保留位域,我们会添加第二个(bc_3bc_4)。请注意bc_5有效。

有趣的是,我们可以选择&#34;比允许更多的比特。见bc_6。这里g ++ - 7发出警告:

bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type
     int a : 40;
             ^~

请注意: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;
    ^

然而,似乎在幕后,编译器会分配另一个int的内存。或者至少,它确定正确的大小。我想编译器警告我们不要以int a = bc_6::a的形式访问这个内存(我敢打赌,int a只会有字段bc_6::a的前32位...)。这由bc_7确认,其总大小为两个int的大小,但第一个字段涵盖了大部分{。}

最后,在上面的示例中使用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