C语言指针算术未打印变量地址时无法正确指向变量问题
问题原因说明
根本原因:你的代码触发了C语言的未定义行为
C标准对指针算术和指针比较有严格的约束:
- 只有指向同一个数组元素(包括数组末尾后一个合法位置)的指针,才能进行加减运算、大小比较操作。
- 你代码里的
d、c、b、a是四个独立的局部变量,C标准没有规定它们在栈上的存储顺序、是否连续、是否存在内存填充间隙,跨独立变量的指针遍历本身就是不被允许的,编译器可以按照任意逻辑处理这类代码。
首次运行跳过8、6的原因
GCC在默认编译(无调试相关代码)时,哪怕不开启优化(-O0),也可能调整局部变量的栈存储布局:
- 可能没有按照你定义变量的顺序连续分配四个int的内存空间,
c、b的存储位置不在&d向低地址递减的路径上 - 极端情况下甚至会把没有被取地址的变量优化到寄存器中,不在栈上分配空间,所以
ptr--遍历的时候会直接跳过c、b对应的内存,访问到的下一个有效变量就是a,所以输出10、4的结果。
添加地址打印代码后恢复正常的原因
当你增加了打印四个变量地址的代码后,编译器必须为四个变量都在栈上分配可寻址的内存空间,为了适配取地址的操作,编译器大概率会按照连续顺序分配四个int的内存,这时候指针增减刚好能遍历到所有变量的地址,输出符合你的预期。
注意:这只是编译器的巧合实现,不属于C标准保证的稳定行为,更换编译选项、编译器版本或者修改其他代码都可能导致问题复现。
正确实现方案
如果需要用指针遍历多个同类型变量,应该把变量存入数组,数组的元素存储是连续、顺序确定的,此时的指针算术才符合C标准要求:
#include <stdio.h> int main(void) { int arr[] = {10, 8, 6, 4}; int *ptr; int len = sizeof(arr) / sizeof(arr[0]); printf("decrement \n"); for (ptr = arr + len - 1; ptr >= arr; ptr--) { printf("%d \n", *ptr); } printf("increment \n"); for (ptr = arr; ptr < arr + len; ptr++) { printf("%d \n", *ptr); } return 0; }
内容的提问来源于stack exchange,提问作者Sininen Blue
相关产品推荐
相关产品推荐

