c - 为什么 GCC 填充这个位域?

标签 c struct padding atomic compare-and-swap

程序是使用 std=c99 的 C 语言,这是在 64 位机器上。

struct epochs {
    volatile unsigned int epoch    : 1;
    volatile unsigned int pulse    : 1;
    volatile unsigned int active0  : 7;
    volatile unsigned int active1  : 7;
    volatile unsigned int counter0 : 24; 
    volatile unsigned int counter1 : 24; 
};

当我检查 sizeof(epochs) 时,它给了我 12。

我可以通过添加 __attribute((packed)); 来告诉 gcc 不要填充它这样我就可以解决这个问题。不过我很想知道为什么要添加 4 个字节来填充这个 64 位结构?

这里最重要的是,这个结构需要是 64 位,因为它是在 64 位原子交换操作中一次性更新的,这当然不适用于 12 字节值。

最佳答案

volatile unsigned int epoch    : 1;
volatile unsigned int pulse    : 1;
volatile unsigned int active0  : 7;
volatile unsigned int active1  : 7;

^ 32 位(4 字节)

volatile unsigned int counter0 : 24; 

^ 32 位(4 字节)

volatile unsigned int counter1 : 24; 

^ 32 位(4 字节)

所以多了 4 个字节。

C 说:

(C99, 6.7.2.1p10) "If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit"

没有足够的空间在 32 位单元中再放入 24 位 (counter0)(可能是系统中 unsigned int 的大小)保存 16 位(epochpulseactive0active1)。

您可以使用uin64_t而不是使用unsigned int将位字段打包到64位单元中,但无论您的系统是否支持它,它都是实现定义的不是。

(C99, 6.7.2.1p4) "A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type."

关于c - 为什么 GCC 填充这个位域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53100520/

相关文章:

C memcpy unsigned char 到 1 元素 unsigned char 数组用于校验和计算

代码打印字符串内的空格

c++ - 将结构的动态数组复制到另一个结构

c - 为什么这个结构文字在 VS2013 中通过地址而不是 gcc/clang 传递时被破坏?

html - 100% 宽度弄乱了填充

c - 从远程线程返回两个值(C,Windows)

c - 通过 HTTP 向网站发送数据

c++ - 使用结构中的 ncurses 扩展字符

struct - 选项类型是否小于包装类型加上 boolean 值?

python - 向图像添加填充以使它们成为相同的形状