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
相关产品推荐
相关产品推荐

