一、const 与指针:权限控制的核心逻辑
核心原则:const 靠近谁,就限制谁的修改权限,共三种核心场景,覆盖所有实用需求。
- 常量指针(const 修饰指向的内容)
规则:指针 p 的指向可修改(能指向其他变量),但 不能通过 *p 修改指向的内容(指向的内存只读)。
代码示例:
实用场景:函数参数传递(如 void printArr(const int *arr, int len) ),防止函数意外篡改数组内容。
- 指针常量(const 修饰指针本身)
规则:指针 p 的指向 不可修改(指针本身是常量),但可通过 *p 修改指向的内容。
代码示例:
避坑点:定义时必须初始化,否则编译报错(常量指针不可悬空)。
- 双重const(同时修饰指针与内容)
规则:指针 p 的指向不可改,且通过 *p 指向的内容也不可改(双重只读)。
代码示例:
适用场景:保护核心数据(如硬件地址、全局配置参数),防止误改指向或内容。
二、野指针:成因与彻底规避方案
野指针是指向「非法内存地址」的指针,会导致程序崩溃、内存污染等问题,必须从源头规避。
- 野指针的三大成因
指针未初始化:定义后未赋值,指向随机内存;
指针越界访问:数组、缓冲区访问超出范围;
内存释放后未置空: free 或函数返回后,指针仍指向已释放的内存。
- 规避野指针的四大技巧
定义即初始化:默认赋 NULL (空指针,指向地址0,不可访问);
内存释放后置 NULL : free§ 后立即 p = NULL ;
用 assert 或条件判断检查指针有效性;
避免指针越界:严格控制数组、缓冲区的访问范围。
代码示例(正确用法)
三、assert 断言:调试阶段的「安全检查工具」
assert 是 C 语言标准库提供的调试工具,用于检查程序运行时的条件是否成立,不满足则直接终止程序并输出错误信息。
- 核心用法
- 特性:仅在「调试模式」生效(Release 模式下会被编译器优化移除),不影响生产环境性能。
- 代码示例(配合指针检查)
- 避坑点: assert 不能替代运行时条件判断(如用户输入校验),仅用于调试阶段的逻辑自检。
四、传值调用 vs 传址调用:函数参数传递的核心差异
函数参数传递的本质是「数据拷贝」,两种调用方式决定了是否能修改实参的值。
- 传值调用(值传递)
原理:将实参的值拷贝给形参,形参是独立变量,函数内修改形参不会影响实参。
代码示例(无法修改实参):
适用场景:仅需使用实参的值,无需修改(如求两数之和、打印数据)。
- 传址调用(地址传递)
原理:将实参的内存地址拷贝给形参(指针变量),函数内通过指针访问并修改实参的内存,直接影响实参。
代码示例(可修改实参):
核心区别:传值传「数据副本」,传址传「数据地址」;需修改实参用传址,仅读用传值。
核心总结
const 管权限:靠近内容则内容只读,靠近指针则指针只读;
野指针要杜绝:定义赋NULL、释放置NULL、访问先检查;
assert 善用:调试阶段查逻辑,Release 模式自动失效;
调用选对:改实参用传址,不修改用传值。