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_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
将只有字段bc_6::a
的前32 位...)。 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
【讨论】:
以上是关于C ++结构语法“a:b”是啥意思的主要内容,如果未能解决你的问题,请参考以下文章