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

C语言指针算术异常行为求助:为何两次代码执行结果不同?

两次C语言指针代码输出差异的原因解析

第一次代码的问题根源

第一次代码里,你在循环中直接修改了foo指针本身:

for (int i = 0; i < 4; i++)
{
    *foo=i+1;  // 给当前foo指向的位置赋值
    foo++;     // foo指针移动到下一个int的地址
    printf("foo[%d] :%d \n",i,foo[i]);  // 这里的foo已经不是初始地址了!
}

执行流程拆解:

  • 初始时foo指向数组首地址(&foo[0])
  • 第1次循环:给foo[0]赋值1,然后foo移动到&foo[1];此时foo[i]即foo[0],访问的是&foo[1]的位置,这个位置还没被赋值,是malloc分配的未初始化内存(你的环境里显示0,是因为glibc在某些场景下会把malloc的内存清零,但这不属于C标准规定的行为)
  • 第2次循环:给&foo[1]赋值2,foo移动到&foo[2];foo[i]即foo[1],访问的是&foo[3]的位置,同样未初始化
  • 后续循环以此类推,最后几次访问的甚至是数组越界的内存,所以输出全是0

第二次代码正确的原因

第二次代码里用ptr保存了foo的初始地址,只移动ptr来完成赋值,而foo始终指向数组的首地址:

int* ptr=foo;  // 保存初始指针,避免修改foo本身
for (int i = 0; i < 4; i++)
{
    *ptr=i+1;  // 给数组的第i个元素赋值
    ptr++;     // 移动ptr到下一个元素
    printf("foo[%d] :%d \n",i,foo[i]);  // foo还是初始地址,foo[i]就是数组的第i个元素
}

执行流程拆解:

  • ptr从数组首地址开始,每次赋值后移动,依次覆盖数组的每个元素
  • foo一直锚定数组开头,foo[i]直接访问的是已经被ptr赋值过的第i个元素,所以输出正确的1-4

关键总结

指针算术的核心是:指针变量本身的值是内存地址,修改指针变量会改变它指向的位置。第一次代码中你修改了唯一指向数组的指针foo,导致后续的数组访问完全偏离了赋值的位置;第二次通过保存初始指针,让foo始终固定在数组首地址,才能正确访问到赋值后的元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:32:53