函数指针和指针函数
1.1 函数指针
函数指针是一个指针,这个指针指向的是一个函数,在之后调用函数的时候,可以通过指针的方式来调用这个函数。为了使函数指针能够指向一个特定的函数,函数指针的声明需要于函数具有类似的结构。
#include <stdio.h>
//声明一个函数
void test(int x)
{
printf("%d\n", x);
}
int main(int argc, char const *argv[])
{
//声明一个函数指针
void (*p)(int );
//给函数指针赋值
p = test;
//通过指针来调用函数
(*p)(2);
return 0;
}
上面这段代码比较简单,首先声明了一个函数,该函数的作用就是将输入到该函数的参数进行打印。在main函数中,定义了一个函数指针。这里需要注意函数指针的定义方式,这个函数指针的方式有点像前面定义二维数组的指针。需要指定该函数的参数列表才能确定这个指针所指向的位置。对函数指针解引用的结果是该函数的地址。
1.2 函数指针的作用
函数指针可以指向一个函数,若是有多个函数需要保存,可以使用一个函数指针数组来将多个同一类型的函数进行保存,有点类似于回调的作用。举个例子就像一个群,群里保存了各个人的联系方式,管理员可以通过这个群直接联系每个人,让被调用的人完成任务。
#include <stdio.h>
void test(int x)
{
printf("%d\n", x);
}
void test_a(int x)
{
printf("%d\n", x);
}
int main(int argc, char const *argv[])
{
void (*p[2])(int );
p[0] = test;
p[1] = test_a;
p[0](2);
p[1](3);
return 0;
}
2.1 指针函数
指针函数是一个函数,这个函数的返回值是一个指针。
int * test(int * p)
{
return p;
}
使用指针函数时,要注意可能会出现野指针的情况。下面这段代码就是一个野指针的实例。
#include<stdio.h>
int * test()
{
int *r = NULL;
int x = 10;
printf("x is %d \n", x);
r = &x;
return r;
}
int main(int argc, char const *argv[])
{
int * p;
p = test();
*p = 2;
printf("*p is %d\n",*p);
test();
printf("*p is %d\n", *p);
return 0;
}
从输出结果可以来分析一下这段代码中存在的问题。在主函数中定义一个指针,最开始调用test()
函数,函数返回了局部变量x的地址,p保存了这个地址,然后p通过解引用将这个地址中的内容更改为2。然后再次调用test()
,可以发现p所指向的内存的数据发生了变化。而这时候我们并没有对指针p做任何操作。从这里可以看到指针p就是一个野指针。
出现这种结果的情况是,函数内部的变量x是局部变量,函数调用完毕后自动释放掉了,但是依然返回了一个地址,返回的地址却被释放掉了,这时候main
函数中的指针p所指向的内容就不归它所有了。
将函数内部的x声明成静态,可以使返回的地址不被释放。
#include<stdio.h>
int * test()
{
int *r = NULL;
static int x = 10;
printf("x is %d \n", x);
r = &x;
return r;
}
int main(int argc, char const *argv[])
{
int * p;
p = test();
*p = 2;
printf("*p is %d\n",*p);
test();
printf("*p is %d\n", *p);
return 0;
}