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

memcmp()行为异常及结构体const修饰影响的原因求助

问题分析与解释

核心问题根源:const修饰的typedef触发未定义行为

你遇到的问题本质是错误地将typedef定义为const限定类型,进而引发了未定义行为,具体拆解如下:

  1. typedef的冗余const导致类型异常
    你的typedef写法:

    typedef const struct drivers {
        char name[DRIVERS_NAME_BUFF_SIZE];
        char version[DRIVERS_VERSION_BUFF_SIZE];
    } const drivers;
    

    这里第二个const完全冗余且不符合C语法规范——typedef的作用是给类型起别名,const是修饰类型而非别名的。实际编译器会将其解析为typedef const struct drivers drivers;,即drivers等价于const struct drivers,意味着所有drivers类型的变量都是不可修改的const对象。

  2. 修改const对象触发未定义行为
    代码中after是const drivers类型,你却调用strcpy(after.name, "my-lib")试图修改它的成员数组——这直接违反了C标准中"不得修改const限定对象"的规定,属于未定义行为。
    编译器对const对象会做特殊优化(比如将其放入只读内存段、或假设其值永远不会改变),这会导致after的实际内存状态和你预期的不一致:比如编译器可能直接忽略strcpy的写入操作,或者写入后内存状态被破坏。

  3. memcmp结果差异的原因

    • res1/res2失败:当直接传递const drivers*类型的指针给memcmp时,编译器会识别到这是指向只读对象的指针,可能基于"const对象不会被修改"的假设进行优化,导致memcmp的比较结果不符合实际内存(比如直接返回非0)。
    • res3成功:uint8_t * base_before = &before;是一个隐式的const指针转非const指针操作(这也是C标准不推荐的),这个转换会绕过编译器对const对象的部分优化,使得memcmp能直接比较实际的内存字节,因此得到了符合预期的结果。
  4. 移除const后正常的原因
    当去掉typedef中的const修饰后,drivers是普通的结构体类型,after变为可修改对象,strcpy的写入操作合法。此时:

    • before用字符串初始化时,数组中未被字符串覆盖的部分会被值初始化为0;
    • after通过{0}初始化,所有数组元素默认是0,strcpy仅覆盖前几个字节,剩余部分保持0;
      两者的内存完全一致,因此所有memcmp都返回0。

修复方案

  1. 修正typedef的写法,去掉冗余的const:
    typedef struct drivers {
        char name[DRIVERS_NAME_BUFF_SIZE];
        char version[DRIVERS_VERSION_BUFF_SIZE];
    } drivers;
    
  2. 如果需要定义不可修改的结构体变量,在变量声明时添加const,而不是在typedef中:
    const drivers before = {.name = "my-lib", .version = "1.2.3.4.5"};
    drivers after = {0}; // 可修改的变量
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:25:54