目录
1. 野指针产生原因和解决方法
在代码编写的过程中,可能会出现指针指向的位置未知,从而出现程序错误,这种指针统一称作野指针。野指针出现的原因最常见的如下几种:
1.1 产生的原因
1.1.1 指针未能初始化
如果一个指针变量被声明但没有被初始化,它会包含一个随机的地址,这个地址很可能不指向有效的内存区域。当你尝试访问这个指针所指向的内存时,就会发生未定义行为或者访问非法内存:
#include <stdio.h>
int main()
{
int* p; // 未初始化的指针
*p = 20;// 这里会导致未定义行为,因为p并没有指向有效的内存
return 0;
}
1.1.2 指针指向的内存被释放
当一个指针指向的内存区域被显式释放(使用 free
函数或者类似的机制)或者超出了其作用域(例如局部变量的指针超出了函数的范围),该指针就成为了野指针。尝试使用或者间接访问这样的指针会导致未定义行为。
int *ptr;
{
int localVar = 10;
ptr = &localVar;
} // localVar 超出作用域,ptr 现在是一个野指针
// 尝试访问 *ptr 将导致未定义行为
1.1.3 指针指向的对象被重复释放
如果一个指针指向的内存已经被释放,但指针本身仍然保持指向已释放的内存,这也会导致野指针的问题。再次使用这个指针可能会导致不可预测的行为或程序崩溃。
int *ptr = malloc(sizeof(int));
free(ptr);
// 现在 ptr 是一个野指针,指向已释放的内存区域
1.2 解决方法
1.2.1 初始化指针
确保每一个指针在使用前都被正确地初始化。
1.2.2 指针空置
当指针不再需要时,将其设置为 NULL
或者 nullptr
(对于 C++)。
1.2.3 避免悬挂指针
在超出作用域之前,确保指针不再指向该作用域内的局部变量。
int *ptr = NULL; // 初始化为 NULL
// 使用前检查指针是否为 NULL
if (ptr != NULL) {
// 只有在 ptr 不为 NULL 时才使用它
}
2. 指针函数和函数指针的区别
2.1 定义不同
指针函数本质是一个函数,其返回值为指针。
函数指针本质是一个指针,其指向一个函数。
2.2 写法不同
指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的:
指针函数:int* fun(int x,int y);
函数指针:int (*fun)(int x,int y);
简单点理解就是:函数名带括号的就是函数指针,否则就是指针函数。
2.3 用法不同
2.3.1 指针函数
指针函数是一个返回指针的函数。它本质上是一个函数,其返回类型是指针类型。这意味着该函数返回一个指针,指向指定类型的数据。指针函数的声明形式为:
*类型标识符 函数名(参数表)
举个例子,首先声明一个普通的函数:
int fun(int x,int y);
我们在声明一个函数,如:
int *fun(int x,int y);
这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。因此想要得到输出值,需要加上解引用运算符*,例如:
#include<stdio.h>
// 定义一个指针函数,返回一个整型指针
int* findMax(int arr[], int size) {
if (size == 0)
return NULL;
int* max = &arr[0];
for (int i = 1; i < size; ++i)
{
if (arr[i] > *max)
{
max = &arr[i];
}
}
return max;
}
int main() {
int numbers[] = { 1, 3, 7, 2, 5 };
int* maxPtr;
maxPtr = findMax(numbers, 5); // 调用指针函数
printf("Max: %d\n", *maxPtr); // 输出最大值
printf("Max: %p\n", maxPtr);
return 0;
}
本函数是一个求数组最大值的函数,若是直接出,则会输出地址,因此需要进行解引用:
普通函数则可进行直接输出:
#include <stdio.h>
// 定义一个普通函数,返回整型值(最大值)
int findMax(int arr[], int size) {
if (size == 0)
return 0; // 如果数组为空,返回一个适当的默认值,这里返回0作为示例
int max = arr[0];
for (int i = 1; i < size; ++i) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
int main() {
int numbers[] = { 1, 3, 7, 2, 5 };
int max = findMax(numbers, 5); // 调用普通函数找到最大值
printf("Max: %d\n", max); // 输出最大值
return 0;
}
2.3.2 函数指针
函数指针是指向函数的指针变量。函数指针存储了函数的地址,可以用来调用该函数。它的声明形式为:
int (*fun)(int x,int y);
函数指针是需要把一个函数的地址赋值给它,有两种写法:
fun = &Function;
fun = Function;
取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
调用函数指针的方式也有两种:
x = (*fun)();
x = fun();
我们进行一个简单的运用:
#include<stdio.h>
//函数+
int add(int x, int y)
{
return x + y;
}
//函数指针
int (*fun)(int x, int y);
int main()
{
int result;
// 将函数指针 fun 分别指向 add 和 sub 函数
fun = add;
result = fun(10, 5); // 调用 add 函数
printf("Result of add: %d\n", result);
fun = &add;
result = fun(10, 5); // 调用 add 函数
printf("Result of add: %d\n", result);
fun = add;
result = (*fun)(10, 5); // 调用 add 函数
printf("Result of add: %d\n", result);
fun = &add;
result = (*fun)(10, 5); // 调用 add 函数
printf("Result of add: %d\n", result);
return 0;
}