C ++结构语法“a:b”是啥意思

Posted

技术标签:

【中文标题】C ++结构语法“a:b”是啥意思【英文标题】:What does C++ struct syntax "a : b" meanC ++结构语法“a:b”是什么意思 【发布时间】:2010-10-23 21:11:52 【问题描述】:

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

struct SMyDataWord

    int Name : 40;
    int Colour : 24;
;

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

在什么系统上 64 位不是 8 字节? 为了迂腐,一个字节中的位数取决于实现(参见 C、C++ 标准中的任何一个)。这是由“限制”标题中的 CHAR_BIT 宏给出的。 一些 IBM 大型机有 9 位字节,IIRC。 ...在这样的系统上(其中一个字节是 3 的倍数),八进制在进行位摆弄时发挥其优势(是的,我知道,我离题了)。 至少 64 个?不准确吗?你的意思是 struct 可能占用超过 64 位?【参考方案2】:

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

【讨论】:

在您提供的 MSDN 链接中,有一行:注意 nYear 是 8 位长,会溢出声明类型 unsigned int 的字边界。所以是从一个新的unsigned int开头开始的。是不是按照上图的解释有误?【参考方案3】:

这是一个位域定义。

Name 是一个整数,可以准确存储 40 位信息。颜色可以存储 24 位。

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

虽然访问位域的代码执行起来会慢一些。

【讨论】:

【参考方案4】:

Use them judiciously:

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

【讨论】:

链接没有把我带到帖子中的报价。【参考方案5】:

这里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 的内存价值(@ 987654331@ 和 bc_2)。曾经,单个int 不能再保存位域,我们添加第二个(bc_3bc_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 将只有字段bc_6::a 的前32 位...)。 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

【讨论】:

以上是关于C ++结构语法“a:b”是啥意思的主要内容,如果未能解决你的问题,请参考以下文章

在C语言中,FUNC是啥意思?

在C语言中,FUNC是啥意思?

在C语言中,FUNC是啥意思?

dart是啥意思

什么是栈?

sql中 identity(1,1)是啥意思