我们知道我们可以创建指向任何数据类型的指针,如int、char、float,我们也可以创建指向函数的指针。函数的代码始终驻留在内存中,这意味着函数具有某个地址。我们可以通过使用函数指针来获取内存的地址。

让我们看一个简单的例子。

#include <stdio.h> 
int main() 
{ 
  printf("main()函数的地址是%p", main); 
  return 0; 
} 

以上代码打印了main()函数的地址。

输出

1.png

从上面的输出中,我们可以观察到main()函数具有某个地址。因此,我们可以得出结论,每个函数都有一个地址。

函数指针的声明

到目前为止,我们已经知道函数有地址,因此我们可以创建指针来存储这些地址,并且可以指向它们。

函数指针的语法

return_type (*ptr_name)(type1, type2…);

例如:

int (*ip)(int);

在上面的声明中,*ip是一个指向返回int值且接受整数值作为参数的函数的指针。

float (*fp)(float);

在上面的声明中,*fp是一个指向返回float值且接受float值作为参数的函数的指针。

我们可以观察到函数的声明与函数指针的声明类似,只是指针前面有一个'*'。因此,在上面的声明中,fp被声明为函数而不是指针。

到目前为止,我们已经学会了如何声明函数指针。下一步是将函数的地址赋给函数指针。

float (*fp)(int, int);  // 函数指针的声明。
float func(int, int);  // 函数的声明。
fp = func;  // 将func的地址赋给fp指针。

在上述声明中,'fp'指针包含'func'函数的地址。

注意:在将函数的地址赋给函数指针之前,必须先声明函数。

通过函数指针调用函数

我们已经知道如何以常规方式调用函数。现在,我们将看到如何使用函数指针调用函数。

假设我们如下声明一个函数:

float func(int, int);  // 函数的声明。

使用常规方式调用上述函数如下所示:

result = func(a, b);  // 使用常规方式调用函数。

使用函数指针调用函数如下所示:

result = (*fp)(a, b);  // 使用函数指针调用函数。

或者

result = fp(a, b);  // 使用函数指针调用函数,可以省略间接运算符。

通过函数名或函数指针调用函数的效果是相同的。如果我们使用函数指针,我们可以省略间接运算符,就像我们在第二种情况中所做的那样。但是,我们仍然使用间接运算符,因为它清楚地告诉用户我们在使用函数指针。

让我们通过一个例子来理解函数指针。

#include <stdio.h> 
int add(int, int); 
int main() 
{ 
  int a, b; 
  int (*ip)(int, int); 
  int result; 
  printf("输入a和b的值:"); 
  scanf("%d %d", &a, &b); 
  ip = add; 
  result = (*ip)(a, b); 
  printf("相加后的值为:%d", result); 
  return 0; 
} 
int add(int a, int b) 
{ 
  int c = a + b; 
  return c; 
}

输出

2.png

将函数的地址作为参数传递给其他函数

我们可以像向函数发送其他参数一样,将函数的地址作为参数传递给其他函数。

通过一个例子来理解。

#include <stdio.h> 
void func1(void (*ptr)()); 
void func2(); 
int main() 
{ 
  func1(func2); 
  return 0; 
} 
void func1(void (*ptr)()) 
{ 
  printf("函数1被调用"); 
  (*ptr)(); 
} 
void func2() 
{ 
  printf("\n函数2被调用"); 
}

在上面的代码中,我们创建了两个函数,即func1()和func2()。func1()函数包含函数指针作为参数。在main()方法中,调用func1()方法,其中我们传递了func2的地址。当调用func1()函数时,'ptr'包含'func2'的地址。在func1()函数内部,我们通过解引用指针'ptr'调用func2()函数,因为它包含了func2的地址。

输出

3.png

函数指针数组

函数指针在我们事先不知道将调用哪个函数的应用程序中使用。在函数指针数组中,数组接收不同函数的地址,并根据索引号调用适当的函数。

通过一个例子来理解。

#include <stdio.h> 
float add(float, int); 
float sub(float, int); 
float mul(float, int); 
float div(float, int); 
int main() 
{ 
  float x;       // 变量声明。
  int y; 
  float (*fp[4])(float, int);    // 函数指针数组的声明。
  fp[0] = add;       // 将函数指针数组的元素赋值为函数的地址。
  fp[1] = sub; 
  fp[2] = mul; 
  fp[3] = div; 
  printf("输入x和y的值:"); 
  scanf("%f %d", &x, &y); 
  float r = (*fp[0])(x, y);    // 调用add()函数。
  printf("\n两个值的和为:%f", r); 
  r = (*fp[1])(x, y);       // 调用sub()函数。
  printf("\n两个值的差为:%f", r); 
  r = (*fp[2])(x, y);      // 调用mul()函数。
  printf("\n两个值的乘积为:%f", r); 
  r = (*fp[3])(x, y);      // 调用div()函数。
  printf("\n两个值的除法为:%f", r); 
  return 0; 
} 
float add(float x, int y) 
{ 
  float a = x + y; 
  return a; 
} 
float sub(float x, int y) 
{ 
  float a = x - y; 
  return a; 
} 
float mul(float x, int y) 
{ 
  float a = x * y; 
  return a; 
} 
float div(float x, int y) 
{ 
  float a = x / y; 
  return a; 
}

在上面的代码中,我们创建了一个函数指针数组,其中包含四个函数的地址。在将函数的地址存储在函数指针数组中之后,我们使用函数指针调用函数。

输出

4.png

标签: c语言, c语言教程, c语言技术, c语言学习, c语言学习教程, c语言下载, c语言开发, c语言入门教程, c语言进阶教程, c语言高级教程, c语言面试题, c语言笔试题, c语言编程思想