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

C语言指针运算结果不符合预期的运行原理解析

C语言指针运算原理说明

核心规则

C语言中指针的加减运算步长由指针指向的类型大小决定:T*类型的指针执行+1操作时,实际偏移的字节数等于sizeof(T),而非偏移1字节。

逐行代码运行解析

我们假设int占4字节,malloc返回的起始内存地址为0x100,你申请的2个连续int内存的地址范围为0x100 ~ 0x107,逐行运行逻辑如下:

  1. int* arr = (int*)malloc(2 * sizeof(int));
    此时arr保存的是申请内存的起始地址0x100,指向第一个int的位置。
  2. arr = arr + 1;
    因为arr是int*类型,加1相当于偏移4字节,此时arr的值变为0x104,指向第二个int的位置。
  3. *arr = 11;
    对当前arr指向的0x104地址赋值,此时0x104位置的值为11。
  4. arr[-1] = 22;
    C语言中下标运算a[b]本质等价于*(a + b),因此arr[-1]就是*(arr - 1),arr当前是0x104,减1后得到0x100,对该地址赋值后0x100位置的值为22。
  5. int x = arr[0]; // x = 11
    arr[0]等价于*(arr + 0),取的是0x104地址的值,因此x为11。
  6. int y = arr[1]; // y = 194759710
    arr[1]等价于*(arr + 1),计算后地址为0x108,已经超出了你malloc申请的内存范围,属于访问未初始化的野内存,得到的是随机垃圾值。

预期结果不符的原因

你错误认为偏移后的arr仍然以原始malloc起始地址为基准计算下标,实际上执行arr = arr + 1之后,arr的基准地址已经变为0x104,所有下标运算都以这个新地址为起点。
如果要得到你预期的x == 22、y == 11,只需要修改取值代码为:

int x = arr[-1];
int y = arr[0];

额外注意事项

你修改了malloc返回的原始指针,后续如果直接调用free(arr)会触发未定义行为,free必须传入malloc返回的原始地址,因此做指针偏移前建议额外保存原始指针:

int* original_arr = (int*)malloc(2 * sizeof(int));
int* arr = original_arr + 1;
// 后续操作完成后free(original_arr)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 03:18:02