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

结构体强制转换后8字节变量仅占4字节的原因排查

问题描述

定义如下结构体:

struct ggg {
    unsigned long long int a;
    unsigned int b;
};

其中字段a预期为8字节,字段b为4字节。尝试将字节数组强制转换为该结构体类型:

unsigned char c[8 + 4] = { 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
                           0x03, 0x00, 0x00, 0x00, };
ggg* g = (ggg *)c ; 
char tt[1024];
sprintf(tt, "a=%d b=%d ", g->a, g->b);

最终tt字符串的结果为:

a=1 b=2

看起来强制转换后a仅占用了4字节而非预期的8字节,请问这是什么原因?

问题原因分析

出现该问题的核心原因有两点:

1. 结构体内存对齐与非法指针转换

C语言中,结构体成员遵循内存对齐规则——为提升CPU访问效率,编译器会在成员间插入填充字节,同时要求结构体起始地址满足最大成员的对齐要求。
对于struct ggg:

  • unsigned long long int a是8字节,要求起始地址对齐到8字节边界;
  • unsigned char数组c没有对齐要求,其起始地址大概率不满足8字节对齐条件。

直接将无对齐的数组指针强制转换为结构体指针属于未定义行为,CPU读取a时会因地址不对齐出现异常,导致a只读取了前4字节,后续4字节被错误识别为b的内容。

2. 格式符与类型不匹配

你用%d打印unsigned long long int类型的a,这是错误的。%d对应int类型(通常4字节),传入8字节的unsigned long long会触发数据截断,进一步加剧结果异常。正确格式符应为%llu(无符号长整型)。

验证与解决建议

  • 查看结构体实际大小:用sizeof(struct ggg)会发现结果是16字节(8字节a + 4字节b + 4字节填充),而非预期的12字节;
  • 避免强制转换无对齐数组:改用memcpy将数组内容拷贝到结构体变量,保证内存对齐;
  • 使用匹配的格式符:unsigned long long用%llu,unsigned int用%u。

修改后的示例代码:

#include <string.h>
#include <stdio.h>

struct ggg {
    unsigned long long int a;
    unsigned int b;
};

int main() {
    // 预留结构体实际大小的空间,包含填充字节
    unsigned char c[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 };
    struct ggg g;
    memcpy(&g, c, sizeof(g));
    char tt[1024];
    sprintf(tt, "a=%llu b=%u ", g.a, g.b);
    printf("%s\n", tt);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:25:19