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

C语言中通过void指针间接修改const变量为何出现地址同值不同?

同一内存地址下,const变量与指针取值为何不同?

你遇到的这个现象,本质是编译器常量折叠优化加上修改const变量属于未定义行为共同导致的,下面具体拆解:

1. 编译器的常量折叠在起作用

当你声明const int const_num = 10;时,因为这个变量是const修饰且初始化值是编译期就能确定的常量,编译器会触发常量折叠优化:把所有直接引用const_num的地方,在编译阶段直接替换成字面量10,完全不会在运行时去对应的内存地址读取值。

所以最后一行printf里的const_num,编译后已经是硬编码的10,根本不会去访问0x16af26db8这个地址的内容——哪怕你用指针把这块内存改成了20,也不影响直接引用const_num的输出。

2. 修改const变量属于未定义行为

C语言标准明确规定:通过指针修改被const限定的对象,属于未定义行为。这意味着编译器对此没有任何固定处理要求,想怎么干都行:

  • 有的编译器会直接拒绝编译这类代码;
  • 有的会让内存值和const变量值同步变化;
  • 就像你的情况,编译器做了常量折叠,导致同一地址出现两种"看似矛盾"的结果。

这种现象完全符合标准,因为未定义行为本身就没有约束,不同环境下表现可能完全不同。

验证常量折叠的影响

如果不想让编译器做常量折叠,可以把const_num的初始化值改成编译期无法确定的,比如用运行时生成的值:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
  srand(time(NULL));
  const int const_num = rand(); // 编译期无法确定值,不会触发常量折叠
  printf("const_num value: %d, const_num address: %p\n", const_num, &const_num);

  void* ptr = (void*)&const_num;
  printf("ptr value: %p, ptr reference value %d\n", ptr, *(int*)ptr);

  *(int*)ptr = 20;
  printf("ptr value: %p, ptr reference value %d\n", ptr, *(int*)ptr);
  printf("const_num value: %d, const_num address: %p\n", const_num, &const_num);

  return 0;
}

这时候编译器没法做常量折叠,直接访问const_num就会读取内存地址的值,输出就会和指针取值一致——但要注意,这种修改行为依然是未定义行为,只是表现出了你预期的结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:42:47