代码之家  ›  专栏  ›  技术社区  ›  Tall Jeff

C++结构语法“A:B”意味着什么?

  •  25
  • Tall Jeff  · 技术社区  · 7 年前

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

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

    什么是 : 40 语法意义…这是否意味着前40位保留名称,其余24位保留颜色?

    这就是它的使用方法,但我以前从未遇到过。

    5 回复  |  直到 8 年前
        1
  •  20
  •   dirkgently    17 年前

    比特场,从C。 Name 40位宽, Colour 是24位宽。因此,结构至少有64位。在我的系统中,64位是8字节。

        2
  •  8
  •   unwind    17 年前

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

        3
  •  6
  •   Nils Pipenbrinck    17 年前

    这是位域定义。

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

    这样做通常是为了在经常需要的结构中节省一些空间,或者将代码压缩到CPU易于处理的大小(在您的例子中是64位)。在64位计算机上的CPU寄存器中。

    但是访问位字段的代码执行速度会稍微慢一些。

        4
  •  3
  •   Özgür    17 年前

    Use them judiciously :

    记住几乎所有关于 位字段是实现 依赖的。例如,位是否 从左到右或 从右到左取决于 硬件架构。此外, 每个编译器使用不同的成员 校准模型,这就是为什么尺寸 优化的billingrec是12 字节而不是9。你不能接受 位字段的地址也不能创建 一组比特。最后,在大多数情况下 实现位字段的使用 增加了开销。因此,当 优化代码,测量 一定优化的效果和 在你决定使用 它。

        5
  •  1
  •   Johannes Blaschke    8 年前

    在这里 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 值得回忆的( 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;
                 ^~
    

    注意: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 只有前32位字段 bc_6::a ……)这是由 bc_7 总尺寸是两个的 int 但是第一个字段覆盖了大部分。

    最后替换 int 具有 长的 在上面的示例中,行为与预期一致:

    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