前一讲鸡啄米给大家讲了指向数组元素的指针和指针数组,这一讲给大家讲讲指针作函数参数的方法和作用,何为指针型的函数,以及指向函数的指针的概念和使用方法。编程入门时指针的内容是难点,望大家细心研究。
一.指针用作函数参数
以前我们学过的函数参数要么是基本数据类型的变量,要么是类的对象,又或者是数组名,前几讲学到的指针同样可以用作函数参数。指针作函数形参时,我们调用此函数将实参值传递给形参后,实参和形参指针变量将指向相同的内存地址,那么在被调函数中对形参指针所指向的对象的改变会一样影响主调函数中实参指针指向的对象。
指针用作函数参数用什么作用呢?其一,使形参指针和实参指针指向相同的内存地址,在被调函数中可以使用主调函数中的数据并可以改变主调函数中的数据,达到数据双向传递的效果。当然,前面讲过的引用也可以实现相同的作用。其二,用指针作函数参数传递数据可以减少参数传递的开销,引用当然也可以实现这些。其三,可以通过指向函数的指针来传递函数代码的首地址。
指针和引用很多时候作用是一样的,引用相对指针来说可读性更好,但有时还是需要使用指针。
鸡啄米把之前讲引用调用时的例程给大家修改下说明指针怎样用作函数参数:
#include <iostream> using namespace std; void Swap(int *a, int *b); int _tmain(int argc, _TCHAR* argv[]) { int x=5, y=10; cout<<"x="<<x<<" y="<<y<<endl; Swap(&x, &y); cout<<"x="<<x<<" y="<<y<<endl; return 0; } void Swap(int *a, int *b) { int t; t=*a; *a=*b; *b=t; }
这里的Swap函数使用了指针作为参数,我们在调用时传入的是x和y的地址,分别传递给了a和b,然后在Swap内部改变了a和b指向的变量的值,而实际上它们指向的就是x和y,所以x和y的值发生了同样的改变。程序运行结果依然是:
x=5 y=10
x=10 y=5
二.指针型函数
函数都有自己的类型,除void类型的函数外都有自己的返回值。函数的返回值也可以是指针。返回值为指针类型的函数就是指针型函数。普通函数只能返回一个变量或对象,但指针型的函数可以在函数调用结束时将大量数据从被调函数返回到主调函数中,这就是它的好处。注意不要返回局部变量的地址,因为出了被调函数局部变量就释放了,返回的地址中存放的内容也是无效的了。
声明指针型函数的语法形式是:
数据类型 *函数名(参数表)
{
函数体
}
数据类型指明了函数返回的指针的类型,“*”和函数名说明这是一个指针型函数,参数表是函数的形参列表。
三.函数指针
我们知道,程序运行时,数据会占用内存空间,实际上程序执行时代码也会调入内存,也会占用内存空间。函数名就是函数代码占用内存空间的首地址。函数指针就是用于存放函数代码首地址的变量。
我们也可以使用函数指针来调用函数,它和函数名实现的作用是一样的。声明方式也类似,也需要指明函数的返回值、形参列表,声明的语法形式是:
数据类型 (*函数指针名)(形参列表);
数据类型指明了函数指针所指向函数的返回值类型,函数指针名给出函数指针的名称,形参列表则说明了函数指针所指函数的形参类型和形参个数。
函数指针和一般的指针一样也要在使用之前先赋值,让它指向一个函数代码的首地址。为函数指针赋值的语法形式是:
函数指针名 = 函数名;
被指向的函数需要是声明过的已存在的,和函数指针必须具有相同的返回值类型、形参个数和形参类型。给函数指针赋值之后我们就可以通过函数指针名来调用它指向的函数了。
鸡啄米给大家一个函数指针的简单程序的例子:
#include <iostream> using namespace std; void show(int x) { cout << x << endl; } void (*show_pointer)(int); // 声明一个void类型的函数指针 int main() { int a = 10; show_pointer = show; // 函数指针show_pointer指向show show_pointer(a); // 函数指针调用 return 0; }
上面例子中声明了一个void类型的函数指针:void (*show_pointer)(int);。我们通过给此函数指针赋值让其指向void类型的函数show,然后用函数指针实现了对函数的调用,输出了a的值。程序运行结果是:10。
今天所讲内容中,指针作函数参数最常用,希望大家能够理解并掌握好。指针型函数和函数指针是两个比较容易混淆的概念,但实际意义又相去甚远,大家可以在很多软件开发公司的面试题中见到。有任何问题可以到鸡啄米博客留言交流。谢谢大家。