为何指向int紧邻内存地址的指针操作仅在偏移3个int时生效?
为什么指针偏移量不同会导致程序运行结果差异?
问题描述
我尝试将指针指向int类型数值的紧邻内存地址,并为该地址写入原数值的两倍。但仅当内存偏移量为3(即3*4,int的大小)或更大时程序才能正常运行,若将偏移量降至2或1,程序无任何输出(出现错误)。
可正常运行的代码:
#include <stdio.h> int main(){ int x, *ptr, memory_jump = 3; scanf("%d",&x); ptr = &x+memory_jump; *ptr = x * 2; printf("Given int = %d, Address = %d \nNext address content = %d,Next address pos = %d",x,&x,*ptr,ptr); return 0; }
出现错误的代码:
int main(){ int x, *ptr, memory_jump = 2; scanf("%d",&x); ptr = &x+memory_jump; *ptr = x * 2; printf("%d", (ptr-2)); printf("Given int = %d, Address = %d \nNext address content = %d,Next address pos = %d",x,&x,*ptr,ptr); return 0; }
请问这两个紧邻内存地址发生了什么情况?
问题解答
首先得给你敲个警钟:你遇到的是C语言中典型的未定义行为——不管偏移量是1、2还是3,这种跨出变量合法内存范围的指针操作都是严格违反C语言标准的,所谓“能正常运行”只是偶然的运气,完全不可靠。
咱们一步步拆解背后的逻辑:
- 单个
int x在栈上占用4字节(假设你的系统中int是4字节),对于指向它的指针&x,C语言只允许你访问两个合法位置:&x(指向x本身)和&x+1(指向x末尾的下一个位置,只能指向但不能解引用)。任何超过这个范围的偏移(比如&x+2、&x+3)都属于越界内存访问。 - 当你执行
*ptr = x * 2时,你在往不属于当前变量的内存地址写入数据,最终结果完全取决于那个地址存储的内容:- 偏移量为3时,
ptr指向的地址刚好是栈上一块“闲置”的、当前进程有权限修改的区域,而且没有覆盖程序运行的关键数据(比如main函数的返回地址、栈帧的控制信息、其他局部变量),所以程序侥幸完成了所有操作并输出结果。但这完全是随机的——换个编译器、操作系统,甚至同一台电脑多次运行,都可能直接崩溃。 - 偏移量为1或2时,
ptr指向的是栈上的关键区域:可能是scanf函数的临时参数、main函数栈帧的返回地址,或者栈帧的其他控制结构。你往这里写入数据直接破坏了程序的执行逻辑,导致程序还没走到printf语句就崩溃了,自然看不到任何输出。
- 偏移量为3时,
关键结论:这种行为没有固定规律,完全是未定义行为的随机性导致的。永远不要编写依赖这种“碰巧能跑”的代码,这是C语言编程中必须避免的危险操作。
内容的提问来源于stack exchange,提问作者Jordan
相关产品推荐
相关产品推荐

