C指针是否始终指向有效内存地址?相关代码运行疑问
C指针是否始终指向有效内存地址?
答案非常明确:绝对不是。咱们一步步来拆解你的问题:
先说说你那段“能运行”的代码到底是怎么回事
你写的这段代码:
int *p; *p = 5; printf("%i",*p); // shows 5
能运行纯粹是撞大运了,这在C语言里叫做未定义行为——意思是C标准根本不规定这段代码该有什么结果,它可能正常打印,可能直接崩溃,可能悄悄破坏其他数据,甚至可能在不同编译器、不同操作系统上表现完全不一样。
为什么会这样?因为你定义了指针p但没有初始化它,这时候p是个野指针,它的值是内存里的随机垃圾值,指向的是一个完全不确定的内存地址:
- 如果这个随机地址刚好属于你的程序有权限访问的内存区域,而且暂时没有被其他重要数据占用,那你给
*p赋值5的时候,就刚好把数据写到了这个“没人用”的地方,之后打印也能读出这个值。 - 但只要运气稍差一点,这个地址可能是操作系统的核心内存(直接触发段错误崩溃),或者是其他变量的内存位置(悄悄修改了其他变量的值,导致后续出现莫名其妙的bug)。这种bug排查起来特别头疼,因为它不是每次都会出现,完全看运气。
再说说正确的写法为什么是安全的
你提到的书籍里的示例:
int *p; int v = 5; p = &v; printf("%i",*p); // shows 5
这才是正确的用法:
- 这里
p被赋值为变量v的地址(&v),v是你定义的局部变量,它的内存地址是属于当前进程的有效地址,完全受你的程序控制。 - 所以你通过
*p访问的是v的内存空间,操作是确定的、安全的,不管在什么环境下运行,结果都是打印5。
最后再提醒几个指针踩坑的常见情况
除了未初始化的野指针,还有几种情况会让指针指向无效地址:
- 悬垂指针:当你用
free()释放了动态分配的内存后,没有把指针置为NULL,这时候指针还指向原来的内存地址,但那块内存已经不属于你的程序了。 - 指向销毁的局部变量:如果指针指向一个函数里的局部变量,函数执行完后局部变量的内存会被回收,这时候指针就变成了野指针。
- 数组越界指针:比如数组
int arr[5];,你用arr[10]访问,这时候指针已经超出了数组的有效内存范围。
C语言是个“信任程序员”的语言,它不会帮你检查指针的有效性,所以使用指针的时候一定要养成好习惯:初始化指针(要么指向有效内存,要么置为NULL),使用前确认指针有效,释放内存后及时置空,避免越界访问。
内容的提问来源于stack exchange,提问作者Naive Developer
相关产品推荐
相关产品推荐

