You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中位字段与联合体的大小疑问及字节压缩需求

解答你的位字段与联合体大小疑问

先直接拆解你的两个问题,再给出压缩到8字节的方案:

1. 为什么结构体data_s的大小是10字节?

问题出在位字段的底层类型上:

  • 你定义uint64_t msg:48时,编译器会为这个位字段分配一个8字节(64位)的存储单元——因为位字段的存储单元大小由其底层类型决定,而非实际使用的位数。
  • 接下来的uint16_t crc:12,底层类型是uint16_t,编译器会再分配一个2字节(16位)的存储单元来存放这12位。
  • 最后的int:0是强制结束当前存储单元的布局,但这里已经用了两个独立的单元(8+2)。#pragma pack(push,1)和__attribute__((packed))只能消除结构体成员之间的填充字节,无法改变位字段底层类型带来的存储单元分配规则。所以总大小就是8+2=10字节。

2. 为什么联合体data_t的大小是16字节?

联合体的大小是其最大成员的大小,再向上对齐到当前平台下最大基本类型的对齐要求:

  • 你的联合体成员中,data_s是10字节,uint64_t是8字节,最大成员是10字节。
  • 在大多数平台上,uint64_t的对齐要求是8字节(即变量地址必须是8的倍数)。10字节需要向上对齐到最近的8的倍数,也就是16字节——这样才能保证联合体中的uint64_t成员始终处于对齐的地址上,避免未对齐访问的问题。

如何将位压缩到8字节中?

核心思路是让所有位字段共享同一个底层类型,这样编译器会把它们打包进同一个存储单元里。修改你的结构体定义,把所有位字段的底层类型统一为uint64_t:

#pragma pack(push, 1)
typedef struct __attribute__((packed)){
    uint64_t msg: 48;   // 底层类型统一为uint64_t
    uint64_t crc: 12;   // 同上
    uint64_t : 4;       // 可选:用匿名位字段填充剩下的4位,也可以省略
} data_s;
#pragma pack(pop)
typedef union {
    uint64_t tot;
    data_s split;
} data_t;

修改后再运行,你会得到输出:Sizes are: union:8,struct:8,uint64_t:8。因为所有位字段都被放在同一个8字节的uint64_t单元里,结构体大小就是8字节;联合体的最大成员是8字节,对齐后还是8字节,完美符合你的需求。

内容的提问来源于stack exchange,提问作者Prateek Dhanuka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:11:43