指针函数和函数指针

本文详细介绍了C语言中的指针概念,包括指针函数、函数指针、指针数组、数组指针和函数指针数组,通过实例演示了它们的声明和用法,帮助读者理解指针在C语言中的核心地位和实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C语言中,指针是一个很重要但是又很容易弄错的概念,也可以说指针就是C语言的灵魂,所以说学好指针对于完全掌握C语言是一个必须的过程。

指针函数

指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”。

声明形式:type *func (参数列表)

为了便于理解,再进一步描述一下。
看看下面这个函数声明:

int fun(int x,int y);

这种函数,其实就是一个函数,然后返回值是一个 int 类型,是一个数值。
接着看下面这个函数声明:

int *fun(int x,int y);

这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。

实例:

#include <iostream>

using namespace std;

int* getNum(int x); //指针函数声明形式

int main()
{
​    cout << "===start===" << endl;
​    int num;
​    cout << "please enter a num: " << endl;
​    cin >> num;
​    cout << "result is: " << *getNum(num) << endl; //输出返回地址中的值 
} 

int* getNum(int x)
{
​    static int num[] = {0,1,2,4,5};
​    return &num[x];  //返回一个地址 
}

输出:

===start===
please enter a num:
3
result is: 4

函数指针

函数指针就是一个指向函数的指针。每个函数在编译时,会被分配一个入口地址,一般用函数名来表示,这个地址就是该函数的指针。

声明形式:type (*func)(参数列表 )

从上面的定义形式可以看出,函数指针和指针函数的直观上区别在于指针符号*与函数名/指针名有没有用括号()包裹起来,从这一点来看是很容易区分两者的。
函数指针是需要把一个函数的地址赋值给它,有两种写法:

func = &Function;
func = Function;

取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
调用函数指针的方式也有两种:

x = (*fun)();
x = fun();

两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。当然,也要看个人习惯,如果理解其定义,随便怎么用都行啦。

实例:

#include <iostream>

using namespace std;

int max(int a, int b)
{
​    return a > b ? a : b;
} 

int main()
{
​    int (*func)(int, int);
​    func = max;
​    int a, b;
​    cout << "please input 2 numbers: " << endl;
​    cin >> a >> b;
​    cout << "max= " << (*func)(a, b) << endl; //使用指针变量调用函数 
​    cout << "max= " << func(a, b) << endl;  //使用函数指针名调用 
​    cout << "max= " << max(a, b) << endl;

​    return 0; 
}

输出:

please input 2 numbers:
3 4
max= 4
max= 4
max= 4

上例给出了函数指针的两种最普遍的调用形式,一个是直接用定义的指针变量(* func)调用,一个是用指针名调用,后者看起来就像是将原函数使用了新名称去调用一样,可以看成函数的别名。再次强调一下:指针变量名和指针符号 * 一定要用括号包裹起来。函数指针还有一种常用的使用方式,就是使用typedef定义后再使用。将上例稍作修改如下:

实例:

#include <iostream>

using namespace std;

int max(int a, int b)
{
​    return a > b ? a : b;
} 

typedef int (*func)(int, int);

int main()
{
​    func maxfunc = max;
​    int a, b;
​    cout << "please input 2 numbers: " << endl;
​    cin >> a >> b;
​    cout << "max= " << (*maxfunc)(a, b) << endl; //使用指针变量调用函数 
​    cout << "max= " << maxfunc(a, b) << endl;  //使用函数指针名调用 
​    cout << "max= " << max(a, b) << endl;

​    return 0; 
}

输出:

please input 2 numbers:
2 4
max= 4
max= 4
max= 4

指针数组

指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。

声明形式:type *var[n]

如int p[n]
[]优先级高,先与p结合成为一个数组,再由int
说明这是一个整型指针数组,它有n个指针类型的数组元素。
指针数组常用在主函数传参,在写主函数时,参数有两个,一个确定参数个数,一个这是指针数组用来接收每个参数(字符串)的地址

int main(int argc, char *argv[])

如果是向子函数传参,这和传递一个普通数组的思想一样,不能传递整个数组过去,如果数组很大,这样内存利用率很低,所以应该传递数组的首地址,用一个指针接收这个地址。因此,指针数组对应着二级指针

void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参

实例:

#include <stdio.h>
#include <string.h>

void sort(char** pa, int n)
{
​    int i, j;
​    char *tmp = NULL;

​    for(i = 0; i < n; i++) {
​       for(j = 0; j < n-i; j++) {
​           if((strcmp(*(pa+j), *(pa+j+1))) > 0) {
​              tmp = *(pa+j);
​              *(pa+j) = *(pa+j+1);
​              *(pa+j+1) = tmp;
​           }
​       }
​       printf("%s\n",*(pa+j));
​    }
}

int main()
{
​    char *pa[4] = {"abc", "def", "xyz", "def"};
​    sort(pa, 4);

​    return 0;
}

输出:

xyz
def
def
abc

数组指针

数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。

声明形式:type (*var)[n]

如int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

实例:

#include <stdio.h>

void fun(int (*a)[4], int m, int n) {
​    printf("%d\n", *(*(a+m)+n));
​    printf("%d\n", *(*(a+m)+n+1));
​    printf("%d\n", *(*(a+m+1)+n));
}

int main()
{
​    int a[3][4] = {{1,2,3,4},{4,3,2,1},{5,6,7,8}};
​    fun(a, 1, 1);

​    return 0;
}

输出:

3
2
6

函数指针数组

顾名思义,就是每个元素都是函数指针的数组,直接在函数指针名后面加上数组符号[ ]即可。

声明形式:type (*func[ ])(参数列表 )

实例:

#include <iostream>

using namespace std;

void fun1() {
​    cout << "fun1 is running" << endl;
}

void fun2() {
​    cout << "fun2 is running" << endl;
}

void fun3() {
​    cout << "fun3 is running" << endl;
}

int main()
{
​    //定义3个函数指针
​    void (*pfun1)() = &fun1;
​    void (*pfun2)() = &fun2;
​    void (*pfun3)() = &fun3;

​    //定义一个数组把它们装进去
​    void(*pfunarr[3])();
​    pfunarr[0] = pfun1;
​    pfunarr[1] = pfun2;
​    pfunarr[2] = pfun3;

/*   pfunarr[0] = &fun1;
​    pfunarr[1] = &fun2;
​    pfunarr[2] = &fun3; */

​    //调用
​    pfunarr[0]();
​    pfunarr[1]();
​    pfunarr[2]();

​    /* //或者调用
​    (*pfunarr[0])();
​    (*pfunarr[1])();
​    (*pfunarr[2])(); */

​    return 0; 
}

输出:

fun1 is running
fun2 is running
fun3 is running

指向函数指针数组的指针

声明形式:type (* (*func )[ ])(参数列表 )

实例:

#include <iostream>

using namespace std;

void fun1() {
​    cout << "fun1 is running" << endl;
}

void fun2() {
​    cout << "fun2 is running" << endl;
}

void fun3() {
​    cout << "fun3 is running" << endl;
}

int main()
{
​    void(*pfunarr[3])();
​    void(*(*pfunarr2)[3])();

​    pfunarr[0] = &fun1;
​    pfunarr[1] = &fun2;
​    pfunarr[2] = &fun3;

​    pfunarr2 = &pfunarr;
​    (*pfunarr2)[0]();
​    pfunarr[0]();

​    return 0; 
}

输出:

fun1 is running
fun1 is running

分析其定义形式:void((pfunarr2)[3])()
其中(
pfunarr2)[3]表示数组指针,而void(
)( )表示函数指针,两者结合起来就是指向函数指针数组的指针。

https://blog.youkuaiyun.com/u010183728/article/details/80967283

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值