指向函数的指针
用函数指针变量调用函数
可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配给一个入口地址。这个函数的入口地址就称为函数的指针。
/****************************/
/* 比较a 和 b的大小,求大值 */
/****************************/
#include <stdio.h>
#if(0)
void main()
{
int max(int, int);
int a, b, c;
scanf("%d %d", &a, &b);
c = max(a, b);
printf("a = %d, b = %d, max = %d\n\n", a, b, c);
}
#endif
int max(int x, int y)
{
int z;
if (x > y)
{
z = x;
}
else
{
z = y;
}
return z;
}
#if(1)
//将 main 函数改写为
#include <stdio.h>
void main()
{
int max(int, int);
int(*p)();
int a, b, c;
p = max;
scanf("%d %d", &a, &b);
c = (*p)(a, b);
printf("a = %d, b = %d, max = %d\n\n", a, b, c);
}
#endif
用指向函数的指针作函数参数
函数指针变量常用的用途之一是把指针作为参数传递到其他函数。
前面介绍过,函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量等。
现在介绍指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。
它的原理可以简述如下:有一个函数(假设函数名为sub),它有两个形参(x1和x2),定义x1和x2为指向函数的指针变量。在调用函数sub时,实参为两个函数名f1和f2,给形参传递的是函数f1和f2的地址。这样在函数sub中就可以调用f1和f2函数了。
实战演练
题目:
设一个函数process,在调用它的时候,每次实现不同的功能。(有点类似多态)
输入a和b两个数,第一次调用process时找出a和b中大者,第二次找出其中小者,第三次求a与b之和。
/***********************************************************/
/* 设一个函数process,在调用它的时候,每次实现不同的功能。*/
/* 输入a和b两个数,第一次调用process时找出a和b中大者,*/
/* 第二次找出其中小者,第三次求a与b之和。 */
/***********************************************************/
#include <stdio.h>
void main()
{
int max(int, int); /* 函数声明 */
int min(int, int); /* 函数声明 */
int add(int, int); /* 函数声明 */
void process(int x, int y, int(*fun)()); /* 函数声明 */
int a, b;
printf("Endter a and b: ");
scanf("%d %d", &a, &b);
printf("max = ");
process(a, b, max);
printf("min = ");
process(a, b, min);
printf("sum = ");
process(a, b, add);
}
int max(int x, int y) /* 函数定义 */
{
int z;
if (x > y)
{
z = x;
}
else
{
z = y;
}
return z;
}
int min(int x, int y) /* 函数定义 */
{
int z;
if (x < y)
{
z = x;
}
else
{
z = y;
}
return z;
}
int add(int x, int y)
{
int z;
z = x + y;
return z;
}
void process(int x, int y, int(*fun)()) /* 函数定义 */
{
int result;
result = (*fun)(x, y);
printf("%d\n", result);
}
返回指针值的函数
一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。
这种带回指针值的函数,一般定义形式为
类型名 *函数名(参数表列);
例如:
int *a(int x,int y);
例题讲解
有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现。
#include <stdio.h>
void main()
{
double score[][4] = { { 60.0, 70.0, 80.5, 90.5 }, { 56.0, 89.0, 67.0, 88.0 }, { 34.2, 78.5, 90.5, 66.0 } };
double *search(double(*pointer)[4], int n);
double *p;
int i, m;
printf("Please enter the number of student: ");
scanf("%d", &m);
printf("The scores of No.%d are: \n", m);
p = search(score, m);
for (i = 0; i < 4; i++)
{
printf("%5.2f\t", *(p + i));
}
printf("\n\n\n");
}
double *search(double(*pointer)[4], int n)
{
double *pt;
pt = *(pointer + n);
return pt;
}
例题升级
对上例中的学生,找出其中有不及格课程的学生及其学生号。
#include <stdio.h>
void main()
{
double score[][4] = { { 60.0, 70.0, 80.5, 90.5 }, { 56.0, 89.0, 67.0, 88.0 }, { 34.2, 78.5, 90.5, 66.0 } };
double *search(double(*pointer)[4], int n);
double *p;
int i, m;
printf("不及格的学生有:\n");
for (i = 0; i < 3; i++)
{
search(score, i);
}
printf("\n\n\n");
}
double *search(double(*pointer)[4], int n)
{
double *pt;
pt = *(pointer + n);
for (int i = 0; i < 4; i++)
{
if ((*pt+i)<60)
{
printf("%d号 ", n);
break;
}
}
}
指针函数和函数指针的区别
这两个概念都是简称:
指针函数是指带指针的函数,即本质是一个函数。
函数指针是指向函数的指针变量,因而函数指针本身首先应是指针变量,只不过该指针变量指向函数。
指针数组和指向指针的指针
指针数组的概念:
一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式为
类型名 数组名[数组长度];
例如:
int *name[4];
从实例来认识问题
#include <stdio.h>
void main()
{
int a[5] = { 1, 3, 5, 7, 9 };
int *name[5] = { &a[0], &a[1], &a[2], &a[3], &a[4] };
int i;
for (i = 0; i < 5; i++)
{
printf("%d ", *name[i]);
}
printf("\n\n");
}
例题分析
例题: 将下边字符串按字母顺序(由小到大)输出。
char *name[]={"Baidu.com", "www.baidu.com", "mpp.csdn.net","cdshn.com/dz"};
提示:
一,我们可以声明一个数组指针来指向;
二,将排序利用strcmp()函数来解决;
三,各个功能抽象为函数或文件。
指针数组
#include <stdio.h>
#include <string.h>
void main()
{
void sort(char *name[], int n);
void print(char *name[], int n);
char *name[] = { "Baidu.com", "www.baidu.com", "mpp.csdn.net", "Baidu.com/dz" };
int n = 4;
sort(name, n);
print(name, n);
}
void sort(char *name[], int n)
{
char *temp;
int i, j, k;
for (i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (strcmp(name[k], name[j]) > 0)
{
k = j;
}
if (k != i)
{
temp = name[i];
name[i] = name[k];
name[k] = temp;
}
}
}
}
void print(char *name[], int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%s\n", name[i]);
}
}
指向指针的指针
怎样定义一个指向指针数据的指针变量呢?
形式可以如: char **p;
p的前面有两个*号。*运算符的结合性是从右到左,因此**p相当于*(*p),显然*p是指针变量的定义形式。如果没有最前面的*,那就是定义了一个指向字符数据的指针变量。
现在它前面又有一个*号,表示指针变量p是指向一个字符指针变量的。*p就是p所指向的另一个指针变量。
#include <stdio.h>
void main()
{
char *name[] = { "Baidu.com", "www.baidu.com", "mpp.csdn.net", "Baidu.com/dz" };
char **p;
int i;
for (i = 0; i < 4; i++)
{
p = name + i;
printf("%s\n", *p);
}
}
指针数组作 main 函数的形参
指针数组的一个重要应用是作为main函数的形参。在以往的程序中,main函数的第一行一般写成以下形式:
void main()
括弧中是空的。实际上,main函数可以有参数。
例如:void main(int argc,char *argv[ ])
argc和argv就是main函数的形参。
main函数是由操作系统调用的。那么,main函数的形参的值从何处得到呢?
显然不可能在程序中得到。实际上实参是和命令一起给出的。也就是在一个命令行中包括命令名和需要传给main函数的参数。
命令行的一般形式为:
命令名 参数1 参数2……参数n
从实例来认识问题
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
int i;
printf("the number of string is : %d\n", argc - 1);
for (i = 1; i < argc; i++)
{
printf("the string %d is : %s\n", i, argv[i]);
}
}