一、指针基本原理
指针实际上就是一个变量,它能存储另一个变量的内存地址。
int var = 10; // 定义一个整型变量 int *ptr = &var; // 定义一个指针,指向var
获取变量的内存地址操作符号:&
访问指针所指向的内存内容操作符号:*
如下图操作:
printf("var的值: %d\n", var); // 输出: 10
printf("var的地址: %p\n", &var); // 输出: var的内存地址
printf("ptr指向的值: %d\n", *ptr); // 输出: 10
二、指针出现的常见问题及解决教程
1、空指针以及野指针的常见问题
未指向任何有效内存时,解引用空指针会导致段错误
int *p = NULL; // 空指针
*p = 1; // 运行时错误:访问空指针
int *q; // 未初始化的野指针
*q = 2; // 未定义行为
解决办法:
①在指针声明时即刻初始化
②在使用之前检查指针是否为NULL
③将内存释放后把指针设置为NULL
2、指针类型匹配错误
double d = 5.20;
int *p = &d; // 警告:指针类型不匹配
解决办法:
①检查指针类型与指向变量是否一致,如不一致则改为一致
②指针转换类型时使用显式转换
3、指针运算时出现错误
访问arr[5]
时超出数组范围,可能导致数据覆盖或程序崩溃
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
p += 10; // 越界访问
解决办法:
①了解指针运算的步长(指针运算的步长由指针所指向的数据类型决定)
②检查是否出现越界符文
③在运用数组时进行边界检查
4、混淆与指针与数组名
sizeof(arr)
返回整个数组的大小(如3 * sizeof(int)
)
sizeof(p)
返回指针的大小(通常4或8字节)
int arr[3] = {1, 2, 3};
int *p = arr;
printf("%zu %zu\n", sizeof(arr), sizeof(p)); // 输出不同!
解决办法:
①数组名在大部分情况下会退化为指针,但sizeof
例外
②传递数组时,额外传递数组长度
5、内存泄漏
程序运行期间,由于未能及时回收动态申请的内存空间,造成内存占用持续增加,长期运行后可能导致系统可用资源被完全占用。
int *p = malloc(10 * sizeof(int));
// 使用后忘记释放
解决办法:
①使用malloc
/calloc
分配内存后,需要配套使用free
②使用工具(如Valgrind)检测内存泄漏,如下代码
int *p = malloc(10 * sizeof(int));
// 使用内存...
free(p); // 释放内存
p = NULL; // 避免悬垂指针
三、指针相关高级用法
1. 指针与数组的关系的运用
数组名在大多数表达式中会被隐式转换为指向该数组首个元素的地址。
int arr[3] = {10, 20, 30};
int *p = arr; // 等价于 &arr[0]
printf("%d\n", arr[1]); // 20
printf("%d\n", *(p+1)); // 20
printf("%d\n", p[1]); // 20 - 指针也可以使用下标
2、多级指针的运用
指向指针的指针,常用于动态二维数组或修改指针本身。
int var = 10;
int *p = &var;
int **pp = &p;
printf("%d\n", **pp); // 输出10
3. 函数指针的运用
指向函数的指针,用于回调函数等场景。
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int (*func_ptr)(int, int); // 声明函数指针
func_ptr = add;
printf("5 + 3 = %d\n", func_ptr(5, 3)); // 8
func_ptr = sub;
printf("5 - 3 = %d\n", func_ptr(5, 3)); // 2
四、总结
以上问题为C语言指针中出现的最常见问题以及分析了相关高级指针用法,解决办法都亲测有效,如果还有什么问题欢迎评论区提问,小编有空帮忙解答大家也可一起探讨,觉得有帮助的话点赞加关注不迷路!!!