“限售烤麸”通过精心收集,向本站投稿了6篇函数指针,以下文章小编为您整理后的函数指针,供大家阅读。
篇1:函数指针
在前面的章节中已经介绍了函数的传指针参数调用,返回指针,根据数组名和指针的等价性,函数的参数也可以是数组,在这些基本概念的基础上,本节讨论指向函数的指针以及带参主函数的相关内容,
指向函数的指针
函数是一组代码的封装体,这组代码在内存中占有一片存储空间,该空间的起始地址存放在以函数名为名的单元的,换言之,函数名就是指向函数的常指针,这有点类似于数组名是指向数组内存空间的常指针。
(1)函数指针的声明和初始化
(2)函数指针使用举例
typedef
为了避免读者对typedef的用法产生误解,前面一直没有介绍typedef的相关内容,介绍完函数指针,来看看typedef的相关内容。
typedef用来给一个已经存在的类型声明一个别名,举一个最简单的例子:
typedef int* int_p; //不要忘记分号
typedef为int* 引入了一个新的助记符int_p,可以在程序中使用int_p声明指向int型变量的指针,如:
int_p pA,pB;
上述代码声明了两个int型指针变量pA和pB,应当注意:typedef不同于编译预处理命令#define,这种不同主要体现在两个方面:
(1)#define是预处理指令,在编译预处理时进行简单的替换,不做正确性检查,不管含义,只是简单的替换,如:
#define PI 3.14
(2)#define结构可以抽象为:
#define A B
通过函数指针将函数作为另一个函数的参数
函数指针的一个功用是把函数地址作为参数传送,以提高函数的通用性和灵活性,如代码7‑10 :
函数指针数组
指向函数的指针还可以组成指针数组,称为函数指针数组,
函数指针数组的使用范例见代码:
(详细内容请参照本书)
返回函数指针的函数
和普通指针一样,函数指针也可以作为另一个函数的返回值,如代码7‑12:
篇2:十七、指针函数和函数指针
一、指针函数
当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中,
格式:
类型说明符 * 函数名(参数)
当然了,由于返回的是一个地址,所以类型说明符一般都是int。
例如:int *GetDate;
int * aaa(int,int);
函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。
int * GetDate(int wk,int dy);
main()
{
int wk,dy;
do
{
printf(Enter week(1-5)day(1-7)\\n);
scanf(%d%d,&wk,&dy);
}
while(wk<1||wk>5||dy<1||dy>7);
printf(%d\\n,*GetDate(wk,dy));
}
int * GetDate(int wk,int dy)
{
static int calendar[5][7]=
{
{1,2,3,4,5,6,7},
{8,9,10,11,12,13,14},
{15,16,17,18,19,20,21},
{22,23,24,25,26,27,28},
{29,30,31,-1}
};
return &calendar[wk-1][dy-1];
}
程序应该是很好理解的,子函数返回的是数组某元素的地址。输出的是这个地址里的值。
二、函数指针
指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型说明符 (*函数名)(参数)
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
例如:
void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
fptr=&Function;
fptr=Function;
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();
第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。下面举一个例子:
void (*funcp)();
void FileFunc(),EditFunc();
main()
{
funcp=FileFunc;
(*funcp)();
funcp=EditFunc;
(*funcp)();
}
void FileFunc()
{
printf(FileFunc\\n);
}
void EditFunc()
{
printf(EditFunc\\n);
}
程序输出为:
FileFunc
EditFunc
三、指针的指针
指针的指针看上去有些令人费解,
它们的声明有两个星号。例如:
char ** cp;
如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到二级指针,三个星号不常见,更别说四个星号了。
指针的指针需要用到指针的地址。
char c='A';
char *p=&c;
char **cp=&p;
通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。下面就是几个这样的例子:
char *p1=*cp;
char c1=**cp;
你可能想知道这样的结构有什么用。利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组。
void FindCredit(int **);
main()
{
int vals[]={7,6,5,-4,3,2,1,0};
int *fp=vals;
FindCredit(&fp);
printf(%d\\n,*fp);
}
void FindCredit(int ** fpp)
{
while(**fpp!=0)
if(**fpp<0) break;
else (*fpp)++;
}
首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实参传递给函数FindCredit()。FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。语句(*fpp)++就是对形参指针指向的指针进行自增运算的。但是因为*运算符高于++运算符,所以圆括号在这里是必须的,如果没有圆括号,那么++运算符将作用于二重指针fpp上。
四、指向指针数组的指针
指针的指针另一用法旧处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理字符串。
char *Names[]=
{
Bill,
Sam,
Jim,
Paul,
Charles,
0
};
main()
{
char **nm=Names;
while(*nm!=0) printf(%s\\n,*nm++);
}
先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针,然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完成上述认为的语法为*nm++,它首先取得指针指向的内容,然后使指针自增。
注意数组中的最后一个元素被初始化为0,while循环以次来判断是否到了数组末尾。具有零值的指针常常被用做循环数组的终止符。程序员称零值指针为空指针(NULL)。采用空指针作为终止符,在树种增删元素时,就不必改动遍历数组的代码,因为此时数组仍然以空指针作为结束。
篇3:C++函数指针详解
学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很 的难点,那就是函数指针了,本博文详细介绍一下常见的各种 的函数指针。
至于指针的详细学习,推荐这篇博文C++指针详解
与数据一样,函数也有地址,函数的地址就是内存中存放函数语言代码的起始地址。函数指针就是指向这个地址。函数指针所指向的类型,就是函数本身。我们知道,指针所指向类型代表了指针所指向的内存区域的大小。所以函数指针所指向的类型,就是函数在内存中所占据内存的大小。知道了函数的起始地址和大小,所以函数指针可以很轻易的代替函数完成函数调用。
一、最简单的函数指针
变量都包括声明和赋值,指针不例外,函数指针也不例外。我们来看一个简单的函数:
void add(int a, int b){
cout << a + b << endl;
}
一个简单的加法计算并输出到命令行的函数。
那么如何通过函数指针来调用它呢?
1、声明:
void (*p1)(int a, int b);
函数指针的声明很简单,基本就是通过一个指针把函数名替换。指针p1的类型为void (*) (int a,int b),表明指针是一个指向某个函数的指针,指针指向的类型为void () (int a,int b)
2、赋值:
p1 = add;
3、也可以直接定义:
void (*p1)(int a, int b) = add;
注意,函数void add(int a,int b)的函数名add就是函数的地址。将地址add赋值给指针p1,那么就可以通过函数指针p1直接调用函数了。
4、调用:
(*p1)(1, 2);
p1(1, 2);
注意!出于历史原因以上2种方式都是可以调用函数的。
二、包含多个函数指针的数组
有时候有这种情况,有一个数组,数组中的每个元素都是一个函数指针,该怎么定义这个数组呢?
1、解释*p[n]和(*p)[n]
我们知道,[]运算符的优先级要高于*,所以,p[3]表示含有3个元素的数组,而*p[3] 前面的 “ * ” 指明了数组中元素的类型,即*p[3]表示一个指向3个指针的数组,
p[3]表示含有3个元素的数组,那么(*p)[3]就是用 *p 替换了 p,很容易想到,(*p)[3] 表示指向一个包含3个元素的数组的指针。
2、声明:
void (*p2[2])(int a, int b);
数组名为p2,数组大小为2,数组中元素类型为void (*)(int a, int b),表明元素是一个指向某个函数的指针,指针指向的类型为void () (int a,int b)。
3、赋值:
p2[1] = add;
理解上跟上面是一样的。
4、调用:
p2[1](2,3);
(*p2[1])(3,4);
同样是2种方式都可以。
三、指向“包含多个函数指针的数组“的指针
这个标题好像有点拗口。简而言之,这个指针指向上文中的 “包含多个函数指针的数组” 。其实很简单,说白了,就是把上文中的p2用一个指针来代替。
1、声明:
void (*(*p3)[2])(int a, int b);
可以看到,无非就是把p2用*p3代替。
2、赋值,注意,既然是指针,使用前必须初始化:
p3 = &p2;
(*p3)[1] = add;
注意!既然实质上就是把p2用*p3代替,c++11可以很简单的这样直接定义:auto p3 = &p2; 代替了void (*(*p3)[2])(int a, int b)= &p2;
3、调用:
(*p3)[1](1, 2);
((*p3)[1])(1, 2);
篇4:C++函数指针简单使用
函数指针必须包含要调用的函数的内存地址,为了工作正确,指针还必须包含其他信息,即指针所指向的函数的参数列表中的参数类型以及返回类型,因此,在声明函数指针时,必须指定该指针可以指向的函数的参数类型和返回类型,以及指针名。
函数指针的一般形式如下:
返回类型(*指针明名)(参数类型列表);
注意:指针名上的括号是必不可少的,否则*就会与返回类型结合,就成了一个函数原型了。
示例:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include
using std::cout;
using std::endl;
//函数声明
long sum(long a,long b);
long product(long a,long b);
int main(int argc,char* argv[]){
//函数指针声明
long (*pfun)(long ,long)=0;
//指向product函数
pfun=product;
cout< < <
return 0;
}
long product(long a,long b){
return a*b;
}
long sum(long a,long b){
return a+b;
}
点击复制链接 与好友分享!回本站首页 分享到: 更多<<“4*6=”<
篇5:C++ 函数指针的详解
1.函数指针
(1)一般来说函数通常包括一系列指令,通过编译后,在内存中占据了一块存储空间,
它有一个起始地址,这个起始(入口)地址就称为函数的指针。
(2)主函数在调用子函数时,就是让程序转移到函数的入口地址开始执行。
(3)我们可以定义一个指针变量用来指向函数,然后通过使用该指针变量调用此函数。
指向函数的指针:就是能够存放某个函数入口地址的指针变量。
总结了一下,函数指针有两个用途:一个是调用函数,另一个是做函数的参数
函数指针定义的一般形式:
数据类型 (*指针变量名)(参数表);
例如:
int (*p); // p为指向返回值为整型数据的函数的指针
float (*q)(float,int); // q为指向返回值为浮点型数据的函数的指针
2.函数指针调用函数的步骤
(1)函数指针变量先要指向函数
定义了指向函数的指针变量,就可以在指针变量与特定函数之间建立关联,让指针变量指向特定函数。
要注意一下:
(1)指针变量只能指向定义时所指定的一类函数,
(2)一个指针变量可以先后指向多个不同的函数。
具体代码:
#include
int arr_add(int (*arr)[4], int n, int m )
void main()
{
int a[3][4] = {1,3,5,7,9,11,13,15,17,19,21,23};
int *p, total1, total2;
int (*pt)(int (*arr)[4], int n, int m );
pt=arr_add;
total1 = arr_add( a,3,4 );
total2 = (*pt)( a,3,4 );
printf( “total1 = %d, total2 = %d\\n”, total1,total2 );
}
int arr_add(int (*arr)[4], int n, int m )
{
int i, j, sum=0;
for(i=0;i
for( j = 0; j< m; j++ )
sum += arr[i][j];
return (sum);
}
篇6:学通C语言:函数型指针
C程序中的函数也都是存放在代码区内的,它们同样也是有地址的,那么如何取得函数的地址呢?在前面也说过函数定义的时候实际上是定义了一个函数变量,那么是否可以将函数变量赋值给其他变量呢?回答这些问题需要涉及另外一个概念:函数型指针。按照已有的指针的知识,顾名思义,函数型指针就是指向函数的指针。如果有一个函数声明为:
int func(const int a, const int b);
那么,此时声明的函数变量add的地址即为这个函数的地址,同时,add的值保存为这个函数的地址,这个特性与数组相似:数组变量与数组变量的地址均为数组的起始地址。而在这个函数声明中,函数类型为int (const int a, const int b)。使用该函数类型来定义一个函数型指针,其方式如下:
int (* fp)(const int a, const int b); /* 其中,参数列表的参数名a和b可省 */
上述语句将变量func定义为指向类型为int (const int a, const int b)的指针操作符和变量名两侧的小括号不可省,否则其含义大不相同。例如:
int * fp(const int a, const int b);
此时,指针操作符与数据类型int结合为int型指针类型,该语句只是声明了一个fp函数,而非定义一个函数指针。为该函数型指针赋值的方式如下:
fp = func;
被赋值的函数变量的类型必须与fp的类型完全一致,包括其返回类型和每一个形参的类型。否则程序将报错。
注意:函数型指针变量赋值时,左值与右值的类型必须完全一致。
使用函数型指针变量调用函数的方法与使用函数变量类似,得到函数地址后再带上参数列表即可。可以使用下面两种方式来调用函数:
fp(5, 6);
或
(*fp)(5, 6);
由于fp被赋值为函数变量func的地址,而func的值又等于其地址,所以*fp可以得到func函数的地址。因此,在调用方式上,可以粗略地将两者视为一致(实际上其后台的处理略有不同)。范例14-7演示了如何使用函数型指针来调用函数。
【范例14-7】使用函数型指针来调用函数,实现方法如示例代码14-7所示。
示例代码14-7
01 #include
02
03 int add(const int a, const int b) { /* 定义add函数 */
04 return a + b;
05 }
06
07 int main(void) {
08 int (*fp) (const int a, const int b); /* 定义函数指针 */
09
10 fp = add; /* 将其赋值为add */
11 printf(“3 + 4 = %d”, fp(3, 4)); /* 使用fp计算+ 4的值 */
12 printf(“3 + 4 = %d”, (*fp)(3, 4)); /* 使用*fp计算+ 4的值 */
13
14 printf(“%p”, add); /* 输出add的值 */
15 printf(“%p”, &add); /* 输出add的地址 */
16 printf(“%p”, fp); /* 输出fp的值 */
17 printf(“%p”, *fp); /* 输出fp指向的值 */
18
19 return 0;
20 }
【运行结果】程序运行后,
【代码解析】本程序定义了一个函数指针,并将其赋值为相应类型的函数变量add。
第11~12行分别使用fp和*fp的方式调用函数,从图14-12的第1~2行中可以看到它们的调用结果是一样的。
第14~17行输出了add的值和地址、fp的值和指向的值,从图14-12的第3~6行中可以看到它们的调用结果都是一样的。
★ 笔试题数组与指针
★ 函数课件
★ 二次函数教案
★ 二次函数练习题
★ 反比例函数测试题
★ 函数的意思
函数指针(精选6篇)




