3

我有以下结构:

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
}

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
}

结构成员对齐是否取决于位域成员的类型?

4

5 回答 5

2
#include <stdio.h>

#define uint64_t unsigned long long
#define uint8_t unsigned char

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
};

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
};
int main(){
    printf("%lu ", sizeof(struct bf_struct1));
    printf("%lu ", sizeof(struct bf_struct2));
    return 0;
}

结果是 8 16。所以我会说答案是肯定的。即使 gcc 和 clang 在我的机器上达成一致,也依赖于编译器。你可以做一些联合,并弄清楚对齐是什么。

于 2013-10-09T15:00:49.283 回答
2
Does the structure member alignment depend on type of a bitfield members?  

是的。

检查byte offsetbit offset

但是,包含位字段的聚合的对齐规则根据有效的对齐模式而有所不同。
在此处输入图像描述

这些规则在此处进行了描述

于 2013-10-09T15:09:16.220 回答
2
  • 位域整体对齐是未指定行为,是否允许位域分配未对齐是实现定义的行为。
  • 位字段的位顺序是实现定义的。
  • 由于上述两点,编译器可以自由地以实现定义的方式在位字段内的任何位置添加填充位和填充字节。
  • uint64_t 是否实际允许在位字段中是实现定义的。所以代码甚至可能不起作用。

如果不阅读特定编译器的文档,真的没有办法知道这段代码会做什么,更不用说它会如何受到对齐的影响。

于 2013-10-09T15:25:48.743 回答
1

是的,它会影响它。在第一个给出的示例中,所有字段都可以放入单个 64-bit uint64-t,因此该结构可能总共需要 8 个字节。但是,第二个可能总共有 16 个字节。前三个字段至少需要两个字节(两个uint8_t)。然后 55 位的最后一个位字段将采用一个uint64_t可能在 8 字节边界上对齐的单个位字段。因此,虽然实际布局取决于编译器,但在两个示例中位的位置会有所不同(因为uint64_t在第二个示例中假设的填充之前。

布局可能类似于以下内容(不完全按比例):

bf_struct1

+---------------+---------+---------+-----------------------------------+
|    uint8_t    | uint8_t | Padding | uint64_t                          |
+---------------+---------+---------+-----------------------------------+
| bf1, bf2, bf3           | 48-bits | bf4                               |
+---------------+---------+---------+-----------------------------------+

bf_struct2

+-----------------------------------+
|      uint64_t                     |
+-----------------------------------+
| bf1, bf2, bf3, bf4                |
+-----------------------------------+
于 2013-10-09T15:00:26.350 回答
1

马口中

6.7.2.1 结构和联合说明符
...
5 位域的类型应为 的合格或不合格版本,或其他一些实现定义的类型。是否允许原子类型是实现定义的。 ..._Bool, signed int, unsigned int

11 实现可以分配任何大到足以容纳位域的可寻址存储单元。如果有足够的空间剩余,紧跟在结构中另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元的对齐方式。

简短的回答:它可以,具体取决于实现。

于 2013-10-09T17:40:18.930 回答