函数在内存中有一个物理位置,而这个位置是可以赋给一个指针的。函数的地址就是该函数的入口点。因此,函数指针可被用来调用一个函数。函数的地址是用不带任何括号或参数的函数名来得到的。(这很类似于数组地址的得到方法,即,在只有数组名而无下标是就得到数组地址。)
1、怎样说明一个函数指针变量呢?
为了说明一个变量fn_pointer的类型是"返回值为int的函数指针",你可以使用下面的说明语句:
int (*fn_pointer) ();
*fn_pointer必须用括号围起来。若漏了这对括号,则int*fn_pointer();的意思完全不同了。fn_pointer将是一个函数名,其返回值为int类型的指针。
2、函数指针变量
在C语言中规定,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为"函数指针变量"。
函数指针变量定义的一般形式为:类型说明符(*指针变量名)();
其中"类型说明符"表示被指函数的返回值的类型。"(*指针变量名)"表示"*"后面的变量是定义的指针变量。最后的空括号表示指针变量所指的是一个函数。例如:int(*pf)();表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。
下面通过例子来说明用指针形式实现对函数调用的方法。
#include <stdio.h> int max(int a,int b) { if(a > b) return a; else return b; } int main() { int max(int a,int b); int(*pmax)(); int x,y,z; pmax = max; printf("inputtwonumbers:\n"): scanf("%d%d",&x,&y); z = (*pmax)(x,y); printf("maxmum=%d",z); }
从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:
1>.先定义函数指针变量,如后一程序中第9行int(*pmax)();定义pmax为函数指针变量。
2>.把被调函数的入口地址(函数名)赋予该函数指针变量,如程序中第11行pmax=max;
3>.用函数指针变量形式调用函数,如:z=(*pmax)(x,y);调用函数的一般形式为:(*指针变量名)(实参表)使用函数指针变量还应注意以下两点:
a.函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
b.函数调用中"(*指针变量名)"的两边的括号不可少,其中的*不应该理解为求值运算,在此处它只是一种表示符号。
看下面的例子:
A) char * (*fun1)(char * p1,char * p2);
B) char * *fun2(char * p1,char * p2);
C) char * fun3(char * p1,char * p2);
看看上面三个表达式分别是什么意思?
C):这很容易,fun3 是函数名,p1,p2 是参数,其类型为char *型,函数的返回值为char *类型。
B):也很简单,与C)表达式相比,唯一不同的就是函数的返回值类型为char**,是个二级指针。
A):fun1是函数名吗?回忆一下数组指针时的情形。数组指针这么定义或许更清晰:int (*)[10] p;
再看看A),这里fun1 不是什么函数名,而是一个指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指针。
再看下面的例子:
#include <stdio.h> #include <string.h> char * fun(char * p1,char * p2) { int i = 0; i = strcmp(p1,p2); if (0 == i) { return p1; } else { return p2; } } int main() { char * (*pf)(char * p1,char * p2); pf = &fun; (*pf) ("aa","bb"); return 0; }
我们使用指针的时候,需要通过钥匙(“*”)来取其指向的内存里面的值,函数指针使用也如此。通过用(*pf)取出存在这个地址上的函数,然后调用它。
3、*(int*)&p ----这是什么?
#include <stdio.h> #include <string.h> void Function() { printf("Call Function!\n"); } int main() { void (*p)(); *(int*)&p=(int)Function; (*p) (); return 0; }
void (*p)();这行代码定义了一个指针变量p,p 指向一个函数,这个函数的参数和返回值都是void。
&p 是求指针变量p 本身的地址,这是一个32 位的二进制常数(32 位系统)。
(int*)&p 表示将地址强制转换成指向int 类型数据的指针。
(int)Function 表示将函数的入口地址强制转换成int 类型的数据。
分析到这里,相信你已经明白*(int*)&p=(int)Function;表示将函数的入口地址赋值给指针变量p。那么(*p) ();就是表示对函数的调用。
讲解到这里,相信你已经明白了。其实函数指针与普通指针没什么差别,只是指向的内容不同而已。
使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。
4、(*(void(*) ())0)()------这是什么?
这是《C Traps and Pitfalls》这本经典的书中的一个例子。下面我们就来分析分析:
第一步:void(*) (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
第二步:(void(*) ())0,这是将0 强制转换为函数指针类型,0 是一个地址,也就是说一个函数存在首地址为0 的一段区域内。
第三步:(*(void(*) ())0),这是取0 地址开始的一段内存里面的内容,其内容就是保存在首地址为0 的一段区域内的函数。
第四步:(*(void(*) ())0)(),这是函数调用。
5、函数指针数组
现在我们清楚表达式“char * (*pf)(char * p)”定义的是一个函数指针pf。既然pf 是一个指针,那就可以储存在一个数组里。把上式修改一下:
char * (*pf[3])(char * p);
这是定义一个函数指针数组。它是一个数组,数组名为pf,数组内存储了3 个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。这念起来似乎有点拗口。不过不要紧,关键是你明白这是一个指针数组,是数组。
函数指针数组怎么使用呢?这里也给出一个非常简单的例子,只要真正掌握了使用方法,再复杂的问题都可以应对。如下:
#include <stdio.h> #include <string.h> char * fun1(char * p) { printf("%s\n",p); return p; } char * fun2(char * p) { printf("%s\n",p); return p; } char * fun3(char * p) { printf("%s\n",p); return p; } int main() { char * (*pf[3])(char * p); pf[0] = fun1; // 可以直接用函数名 pf[1] = &fun2; // 可以用函数名加上取地址符 pf[2] = &fun3; pf[0]("fun1"); pf[0]("fun2"); pf[0]("fun3"); return 0; }
6、定义一个简单的函数指针数组指针:
char * (*(*pf)[3])(char * p);
注意,这里的pf 和上一节的pf 就完全是两码事了。上一节的pf 并非指针,而是一个数组名;这里的pf 确实是实实在在的指针。这个指针指向一个包含了3 个元素的数组;这个数字里面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。这比上一节的函数指针数组更拗口。其实你不用管这么多,明白这是一个指针就ok 了。其用法与前面讲的数组指针没有差别。下面列一个简单的例子:
#include <stdio.h> #include <string.h> char * fun1(char * p) { printf("%s\n",p); return p; } char * fun2(char * p) { printf("%s\n",p); return p; } char * fun3(char * p) { printf("%s\n",p); return p; } int main() { char * (*a[3])(char * p); char * (*(*pf)[3])(char * p); pf = &a; a[0] = fun1; a[1] = &fun2; a[2] = &fun3; pf[0][0]("fun1"); pf[0][1]("fun2"); pf[0][2]("fun3"); return 0; }
相关推荐
C语言指针函数和函数指针详细介绍 C语言中指针函数和函数指针是两个不同的概念,但它们之间存在着紧密的联系。本文将对C语言中的指针函数和函数指针进行详细的介绍。 一、指针函数 指针函数是指返回值为指针的...
一、函数指针的定义 顾名思义,函数指针就是函数的指针。它是一个指针,指向一个函数。看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun2(char * p1,char * p2); C) char * fun3(char * p1,char * ...
C语言函数指针小结 C语言函数指针是C语言中一个重要的组成部分,使用函数指针编程有以下优点: 1. 提高程序的编译效率和执行速度。 2. 通过函数指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现...
在C语言中,函数指针和指针函数是高级特性,它们在编程中扮演着重要角色,尤其是在处理回调函数、动态调度以及实现元编程等方面。本训练将深入讲解这两个概念,帮助你掌握其核心概念和实际应用。 首先,我们要了解...
以下是对C语言函数指针的详细说明: 1. **指针基础**: - 指针是C语言的核心部分,它可以存储内存地址,使得我们能直接操作内存。 - 指针的运算包括取地址运算符`&`,取内容运算符`*`,赋值运算,加减运算以及...
### C语言指针详解:函数指针与指针函数 #### 第十章 指针 **一、指针的基本概念** 指针是C语言中一个非常重要的概念,它允许程序员直接操纵内存地址,这对于提高程序效率至关重要。理解指针的基础概念是学好...
c语言函数指针和指针函数[收集].pdf
### C语言中关于函数指针的用法 在C语言中,函数指针是一种非常强大的特性,它允许程序员将函数当作参数传递给其他函数或在运行时决定调用哪个函数,这种灵活性对于实现某些高级算法(如排序算法中的比较函数)至关...
- **函数指针**:可以存储函数地址的变量,使得函数可以作为参数传递或作为其他函数的返回值。 4. **指针**: - 指针是C语言的一大特色,它存储了一个变量的内存地址。 - 指针的声明、初始化和解引用是学习的...
"C语言指针数组函数笔记" ...本笔记总结了C语言中的指针和数组相关知识点,涵盖了变量、指针变量、指针运算符、数组和指针数组函数等内容。通过阅读本笔记,读者可以更好地理解和应用C语言中的指针和数组。
课程思政促进C语言函数指针教学的实践
【C语言函数指针】是C语言中一种高级特性,它允许我们将函数的地址作为其他函数的参数,或者存储在变量中,以便后续调用。理解函数指针是深入掌握C语言的重要步骤。 首先,我们要了解函数在C语言中的本质。在C语言...
例如,`void (*func_ptr)(int)`定义了一个接受整数参数的函数指针类型,我们可以将函数的地址赋值给它,然后通过这个指针调用相应的函数。 总之,《C语言-指针总结-经典讲解》涵盖了从基础到进阶的指针知识,包括...
C语言中指针、数组和函数的综合应用与实例解析 本文对C语言中指针、数组和函数的概念、运算和应用进行了详细的探讨和分析。指针是C语言的重要特色,是一种特殊的数据类型,通过存储空间的地址或编号来访问数据。...
《C语言指针经验总结》PDF是一份深入探讨C语言指针使用技巧和实践经验的文档。C语言中的指针是其强大特性的核心之一,它允许程序员直接操作内存,实现高效的数据处理和灵活的程序设计。这份资料通过实例和经验分享,...
总结来说,“C语言函数大全”这个资源应该涵盖了函数的各个方面,包括但不限于函数的定义、参数传递、返回值、函数指针、递归、函数优化等。通过对这些例题的学习和实践,学习者能更深入地理解C语言函数的使用,并...
在C语言中,函数指针是一种强大的特性,它允许我们存储函数的地址并直接通过指针调用函数,使得在程序中动态地决定执行哪个函数成为可能。下面将详细讲解函数指针的概念、定义方式、使用方法以及示例。 1. **函数...
在C语言中,指针函数和函数指针是两个经常被提及的概念,但很多初学者在理解上可能会感到困惑。这篇文章将详细地对这两个概念进行介绍,以便大家能更好地掌握C语言。 首先,我们需要明确什么是函数指针。函数指针是...
本篇将详细介绍C语言函数的相关知识点,并通过“C函数库”这一压缩包中的文档,帮助你更好地理解和使用C语言函数。 1. **函数定义与调用**: 在C语言中,函数是代码块的封装,可以执行特定任务。函数定义包括返回...