C 语言编程中的函数指针及其示例

指针为“C”函数提供了极大的可能性,而这些函数只能返回一个值。有了指针参数,我们的函数现在可以处理实际数据,而不是数据的副本。

为了修改变量的实际值,调用语句将地址传递给函数中的指针参数。

函数指针示例

例如,下一个程序交换两个值:

void swap (int *a, int *b);
int main() {
  int m = 25;
  int n = 100;
  printf("m is %d, n is %d\n", m, n);
  swap(&m, &n);
  printf("m is %d, n is %d\n", m, n);
  return 0;}
void swap (int *a, int *b) {
  int temp;
  temp = *a;
  *a = *b;
  *b = temp;}
}

输出:

m is 25, n is 100
m is 100, n is 25

函数指针示例

程序交换实际变量的值,因为函数使用地址访问它们 指针下面我们来讨论一下程序流程:

  1. 我们声明负责交换两个变量值的函数,该函数以两个整数指针作为参数,并在调用时返回任意值。
  2. 在主函数中,我们声明并初始化两个整数变量(“m”和“n”),然后分别打印它们的值。
  3. 我们通过使用 & 符号将两个变量的地址作为参数传递来调用 swap() 函数。之后,我们打印新的交换变量值。
  4. 这里我们定义了swap()函数内容,它以两个整型变量地址为参数,并声明一个临时整型变量,作为第三个存储盒,用来保存将要放入第二个变量中的一个值变量。
  5. 将‘a’指向的第一个变量的内容保存在临时变量中。
  6. 将 b 指向的第二个变量存储在 a 指向的第一个变量中。
  7. 使用临时变量中保存的第一个变量的值更新第二个变量(b 指向)。

带有数组参数的函数

在 C 语言中,我们不能将数组按值传递给函数。然而,数组名称是一个指针(地址),所以我们只需将数组名称传递给函数,这意味着将指针传递给数组。

例如,我们考虑以下程序:

int add_array (int *a, int num_elements);
int main() {
  int Tab[5] = {100, 220, 37, 16, 98};
  printf("Total summation is %d\n", add_array(Tab, 5)); 
  return 0;}
int add_array (int *p, int size) {
  int total = 0;
  int k;
  for (k = 0; k < size; k++) {
    total += p[k];  /* it is equivalent to total +=*p ;p++; */}
 return (total);}

输出:

 Total summation is 471

这里我们将详细解释程序代码

带有数组参数的函数

  1. 我们声明并定义 add_array() 函数,该函数以数组地址(指针)及其元素数量作为参数,并返回这些元素的总累计和。指针用于迭代数组元素(使用 p[k] 表示法),我们将总和累积在局部变量中,迭代整个元素数组后将返回该变量。
  2. 我们声明并初始化一个包含五个整数元素的整数数组。我们将数组名称(充当地址)和数组大小传递给 添加数组()调用函数作为参数。

返回数组的函数

在 C 语言中,我们可以返回一个指向数组的指针,如下面的程序所示:

#include <stdio.h>
int * build_array();
int main() {
  int *a;
  a = build_array(); /* get first 5 even numbers */
  for (k = 0; k < 5; k++)
    printf("%d\n", a[k]);
  return 0;}
int * build_array() {
  static int Tab[5]={1,2,3,4,5};
   return (Tab);}

输出:

1
2
3
4
5

在这里,我们将讨论计划细节

返回数组的函数

  1. 我们定义并声明一个函数,该函数返回一个包含整数值的数组地址并且不接受任何参数。
  2. 我们声明一个整数指针,它接收函数调用后构建的完整数组,并通过迭代整个五元素数组来打印其内容。

请注意,定义指针(而不是数组)来存储函数返回的数组地址。还要注意,当从函数返回局部变量时,我们必须在函数中将其声明为静态。

函数指针

根据定义我们知道指针指向任何内存位置的地址,它们也可以指向内存中函数形式的可执行代码的开头。
指向函数的指针用*来声明,其声明的一般语句为:

return_type (*function_name)(arguments)

您必须记住 (*function_name) 周围的括号很重要,因为如果没有它们,编译器会认为 function_name 返回的是 return_type 的指针。
定义函数指针后,我们必须将其分配给一个函数。例如,下一个程序声明一个普通函数,定义一个函数指针,将函数指针分配给普通函数,然后通过指针调用该函数:

#include <stdio.h>
void Hi_function (int times); /* function */
int main() {
  void (*function_ptr)(int);  /* function pointer Declaration */
  function_ptr = Hi_function;  /* pointer assignment */
  function_ptr (3);  /* function call */
 return 0;}
void Hi_function (int times) {
  int k;
  for (k = 0; k < times; k++) printf("Hi\n");}

输出:

Hi
Hi
Hi

C 语言中的函数指针

  1. 我们定义并声明一个标准函数,该函数在调用时打印 k 次 Hi 文本(由参数 times 指示)
  2. 我们定义一个指针函数(带有其特殊声明),它接受一个整数参数并且不返回任何内容。
  3. 我们用 Hi_function 初始化我们的指针函数,这意味着指针指向 Hi_function()。
  4. 我们不是通过将函数名与参数结合起来进行标准函数调用,而是通过传递数字 3 作为参数来调用指针函数,就是这样!

请记住,函数名指向可执行代码的起始地址,就像数组名指向其第一个元素一样。因此,像 function_ptr = &Hi_function 和 (*funptr)(3) 这样的指令是正确的。
注意:在函数赋值和函数调用期间插入地址运算符&和间接运算符*并不重要。

函数指针数组

函数指针数组可以充当 switch 或 if 语句的角色来做出决策,如下一个程序所示:

#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int div(int num1, int num2);

int main() 
{  int x, y, choice, result;
  int (*ope[4])(int, int);
  ope[0] = sum;
  ope[1] = sub;
  ope[2] = mult;
  ope[3] = div;
  printf("Enter two integer numbers: ");
  scanf("%d%d", &x, &y);
  printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
  scanf("%d", &choice);
  result = ope[choice](x, y);
  printf("%d", result);
return 0;}

int sum(int x, int y) {return(x + y);}
int sub(int x, int y) {return(x - y);}
int mult(int x, int y) {return(x * y);}
int div(int x, int y) {if (y != 0) return (x / y); else  return 0;}
Enter two integer numbers: 13 48
Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2
624

下面,我们来讨论一下该计划的细节:

函数指针数组

  1. 我们声明并定义四个 功能 它接受两个整数参数并返回一个整数值。这些函数根据用户调用的函数对两个参数进行加、减、乘、除运算。
  2. 我们声明了 4 个整数,分别用于处理操作数、操作类型和结果。此外,我们声明了一个包含四个函数指针的数组。数组元素的每个函数指针都接受两个整数参数并返回一个整数值。
  3. 我们用已经声明的函数分配并初始化每个数组元素。例如,第三个元素即第三个函数指针将指向乘法运算函数。
  4. 我们从用户用键盘输入的内容中寻找操作数和操作类型。
  5. 我们用参数调用适当的数组元素(函数指针),并存储适当函数生成的结果。

指令 int (*ope[4])(int, int); 定义函数指针数组。每个数组元素必须具有相同的参数和返回类型。
语句 result = ope[choice](x, y); 根据用户的选择运行适当的函数 输入的两个整数是传递给该函数的参数。

使用 void 指针的函数

在函数声明期间使用 void 指针。我们使用 void * 返回类型允许返回任何类型。如果我们假设我们的参数在传递给函数时不会改变,我们将其声明为 const。
例如:

 void * cube (const void *);

考虑以下程序:

#include <stdio.h>
void* cube (const void* num);
int main() {
  int x, cube_int;
  x = 4;
  cube_int = cube (&x);
  printf("%d cubed is %d\n", x, cube_int);
  return 0;}

void* cube (const void *num) {
  int result;
  result = (*(int *)num) * (*(int *)num) * (*(int *)num);
  return result;}

结果:

 4 cubed is 64

在这里,我们将讨论该计划的细节:

使用 void 指针的函数

  1. 我们定义并声明一个函数,该函数返回一个整数值,并获取一个不带特定数据类型的不可更改变量的地址。我们计算 num 指针指向的内容变量 (x) 的立方值,由于它是一个 void 指针,我们必须使用特定符号 (* datatype) 指针将其转换为整数数据类型,然后返回立方值。
  2. 我们声明操作数和结果变量。此外,我们用值“4”初始化操作数。
  3. 我们通过传递操作数地址来调用立方体函数,并在结果变量中处理返回值

函数指针作为参数

利用函数指针的另一种方法是将其作为参数传递给另一个函数,有时称为“回调函数”,因为接收函数“将其回调”。
在 stdlib.h 头文件中,Quicksort“qsort()”函数使用了这种技术,它是一种专用于对数组进行排序的算法。

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void *base:指向数组的 void 指针。
  • size_t num :数组元素数量。
  • size_t width 元素大小。
  • int (*compare (const void *, const void *) :由两个参数组成的函数指针,当参数具有相同的值时返回 0,当 arg0 在 arg1 之前时返回 <2,当 arg0 在 arg1 之后时返回 >2。

以下程序使用 qsort() 函数对整数数组从小到大进行排序:

#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *); 
int main() {
  int arr[5] = {52, 14, 50, 48, 13};
  int num, width, i;
  num = sizeof(arr)/sizeof(arr[0]);
  width = sizeof(arr[0]);
  qsort((void *)arr, num, width, compare);
  for (i = 0; i < 5; i++)
    printf("%d ", arr[ i ]);
  return 0;}
int compare (const void *elem1, const void *elem2) {
  if ((*(int *)elem1) == (*(int *)elem2))  return 0;
  else if ((*(int *)elem1) < (*(int *)elem2)) return -1;
  else return 1;}

结果:

 13 14 48 50 52

在这里,我们将讨论该计划的细节:

函数指针作为参数

  1. 我们定义由两个参数组成的比较函数,当参数具有相同的值时返回 0,当 arg0 在 arg1 之前时返回 <2,当 arg0 在 arg1 之后时返回 >2。参数是 void 指针类型,转换为适当的数组数据类型(整数)
  2. 我们定义并初始化一个整数数组,数组大小存储在 NUM 变量,每个数组元素的大小存储在使用 sizeof() 预定义的 width 变量中 C 运算符.
  3. 我们称 排序 函数并传递数组名称、大小、宽度和用户先前定义的比较函数,以便按升序对数组进行排序。比较将通过每次迭代获取两个数组元素来执行,直到对整个数组进行排序。
  4. 我们通过使用以下方法迭代整个数组来打印数组元素,以确保数组排序正确 for循环.