C语言之指针详解(6)

简介: 本章重点1. 字符指针2. 数组指针3. 指针数组4. 数组传参和指针传参5. 函数指针6. 函数指针数组7. 指向函数指针数组的指针8. 回调函数9. 指针和数组面试题的解析

指向函数指针数组的指针

指向函数指针数组的指针是一个指针指针指向一个数组 ,数组的元素都是函数指针

我们看代码

根据定义

//int(*(*ppArr)[5])(int, int);

看这个代码,*先和ppArr结合说明ppArr是一个指针,然后再和【5】结合说明这是一个数组指针,我们把(*paArr)【5】去掉来看效果

2405a690b88849b985565983fe76091d.png

//int(*)(int, int);

这个代码的意思是*先和()结合说明他是一个指针,再和(int,int)结合说明他是一个函数指针,并且这个函数的返回类型为Int型

612915c47b2542598561d0c574e2c284.png

接下来我们来看回调函数

那什么是回调函数呢?

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当 这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调 用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应

那我们来看下面代码

#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
  int i = 0;
  //趟数
  for (i = 0; i < sz - 1; i++)
  {
    //一趟冒泡排序
    int j = 0;
    for (j = 0; j < sz - 1 - i; j++)
    {
      if (arr[j] > arr[j + 1])
      {
        int tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
      }
    }
  }
}
struct Stu
{
  char name[20];
  int age;
};
int main()
{
  int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  struct Stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };
  bubble_sort(arr, sz);//这个冒泡排序类型只能排序整型,不能排序其他类型
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

8abd04f2388346458966e4b5ed1dd32f.png


那我们如何优化这种代码呢???这里我们需要了解一下qsort库函数

qsort----quick sort快速排序

259cb52cc56e4dbcab12247cee68da1f.png

qsort库函数有4个参数,这里重点说一下最后一个参数,这里的*先和compar结合,说明他是一个桌指针,然后再和(const void*,const void*e2)结合说明

这是一个函数,这就是一个函数指,且函数的返回类型为int型

723f152de4654c7a88b080ea1dd5e113.png

给大家解释一下这四个参数分别代表的意思


base:目标数组的起始位置


num:数组的大小(单位为元素),也就是数组有几个元素


size:元素的大小(单位为字节),也就是一个元素的大小(单位为字节)


compar:比较


现在我们来看代码


#include<stdio.h>
#include<stdlib.h>
void qsort(void* base, size_t num, size_t size, int (*compar)(const void* e1, const void* e2));
int cmp_int(const void* e1, const void* e2)
{
}
int main()
{
  int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  //struct Stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };//结构体数组
  //bubble_sort(arr, sz);//这个冒泡排序类型只能排序整型,不能排序其他类型
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

9ddb9f87e24244bdb2fb8c689dbcde0b.png

我们把cmp_int函数放到qsort这个函数中,,函数名和参数值以及返回类型和qsort的第四个参数的函数参数以及函数的返回值是一致的,所以我们就可以通过(*compar)找到cmp_int这个函数名(也可以叫做是函数的地址)大家这里可能有个疑问,我们见过int*,char*,double*,float*等等,但是没有见过void*,我这里给大家解释一下,我们来看代码


#include<stdio.h>
int main()
{
  int a = 10;
  int* pa = &a;
  char* pc = &a;
  void* p = &a;
  p = &pc;
  //void*类型的指针,可以接收任意类型的地址
}

207b80dedb184af2a9a8c21c7b9053db.png

void*类型的指针,可以接收任意类型的地址


当我们要排序其他的类型(int*,char*等等),这是void就可以接收这些类型,就不用我们多次去改变变量类型


我们来看一下void*类型需要注意的事项,我们看代码


#include<stdio.h>
int main()
{
  int a = 10;
  int* pa = &a;
  char* pc = &a;
  void* p = &a;
  *p = 0;
  p++;
  //void*类型的指针,可以接收任意类型的地址
  //void*类型的指针,不能进行解引用操作
  //void*类型的指针,不能进行+-整数的操作
}

7b0d9cb691154475b84fd756734ff445.png


我们接着来看刚才我们写到的qsort函数,这里的void*指针变量的值不能被改变(不能解引用),我们需要强制类型转换,强制类型转换为int*类型的指针就可以进行*解引用了


打印出来是从小到大的升序数组


#include<stdio.h>
#include<stdlib.h>
//void qsort(void* base, size_t num, size_t size, int (*compar)(const void* e1, const void* e2));
int cmp_int(const void* e1, const void* e2)
{
  return *(int*)e1 - *(int*)e2;
}
int main()
{
  int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  //struct Stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };//结构体数组
  //bubble_sort(arr, sz);//这个冒泡排序类型只能排序整型,不能排序其他类型
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}


0568fa70d8854edcb9360c6b71e71b87.png


结构体数组的快速排序和float类型的快速排序我将在下一个博客的开头给大家做详细的讲解!


本章终,这一章节难度大,大家多消化理解一下


相关文章
|
11月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
189 1
|
7月前
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
138 0
|
9月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
301 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
9月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
1115 9
|
9月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
270 7
|
10月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
864 13
|
10月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
310 11
|
10月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
10月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
10月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
604 3