C++;结构语法;a:b";意思是 如果我有一个C++结构,定义一个64位的数据字,比如. struct SMyDataWord { int Name : 40; int Colour : 24; };

C++;结构语法;a:b";意思是 如果我有一个C++结构,定义一个64位的数据字,比如. struct SMyDataWord { int Name : 40; int Colour : 24; };,c++,data-structures,syntax,struct,C++,Data Structures,Syntax,Struct,:40语法是什么意思。。。这是否意味着前40位用于名称,其余24位用于颜色 这就是它的使用方式,但我以前从未遇到过。位字段,从C继承而来。Name宽40位,color宽24位。因此,结构至少有64位。在我的系统上,64位将是8字节。位字段,从C带入。名称是40位宽,颜色是24位宽。因此,结构至少有64位。在我的系统上,64位是8字节。是的,这是的语法。它们通常用于定义映射到硬件寄存器的结构。如果您决定使用它们,有一些事情需要记住,其中之一是您不知道编译器是如何进行布局的,组成字段的实际字节中的排

:40
语法是什么意思。。。这是否意味着前40位用于名称,其余24位用于颜色


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

位字段,从C继承而来。
Name
宽40位,
color
宽24位。因此,结构至少有64位。在我的系统上,64位将是8字节。

位字段,从C带入。
名称
是40位宽,
颜色
是24位宽。因此,结构至少有64位。在我的系统上,64位是8字节。

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

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

这是一个位字段定义

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

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


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

这是一个位域定义

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

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

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

记住,几乎所有关于 位字段是实现的基础 依赖的。例如,是否 从左到右或从右存储 从右到左取决于实际情况 硬件架构。此外,, 每个编译器使用不同的成员 对齐模型,这就是为什么 优化后的BillingRec的平均值为12 字节而不是9。你不能拿一张支票 位字段的地址也不能创建 一种位数组。最后,在大多数情况下 位字段的使用 导致速度开销。所以,什么时候? 优化代码,测量 一定的优化和优化效果 在您决定使用之前,需要进行权衡 它

:

记住,几乎所有关于 位字段是实现的基础 依赖的。例如,是否 从左到右或从右存储 从右到左取决于实际情况 硬件架构。此外,, 每个编译器使用不同的成员 对齐模型,这就是为什么 优化后的BillingRec的平均值为12 字节而不是9。你不能拿一张支票 位字段的地址也不能创建 一种位数组。最后,在大多数情况下 位字段的使用 导致速度开销。所以,什么时候? 优化代码,测量 一定的优化和优化效果 在您决定使用之前,需要进行权衡 它


这里
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;
}
这告诉我们一些事情:如果
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
将只具有字段
bc_6::a
的前32位)。这一点由总大小为两个
int
s的
bc_7
确认,但第一个字段涵盖了其中的大部分

最后,在上述示例中,将
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

这里
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;
}
这告诉我们一些事情:如果
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
值的内存。或者至少,它决定了正确的大小。我猜是编译器