带你深入了解c语言指针后续

简介: 带你深入了解c语言指针后续

一、函数指针


1.1 函数指针的创建


函数指针,顾名思义,就一个指向函数的指针.


那么


整形指针是接收整形的地址;


字符指针是接收字符的地址.


数组指针是接收数组的地址


函数有地址吗?函数名又可以代表什么?


示例:自定义一个加法函数,观察函数的地址


//函数指针
#include <stdio.h>
int add(int a,int b)//自定义一个加法函数
{
  return a + b;
}
int main()
{
  int a = 2, b = 3;
  int c=add(a, b);
  printf("%d\n", c);//确认一下函数是否正确
  printf("%p\n", &add);//取出函数的地址
  printf("%p\n", add);//用数组名打印
  return 0;
}


运行结果:(在不同环境下地址会不一样,这里采用的是vs x86环境)


5


00E61023


00E61023


不难发现,函数名也可以代表函数的地址.


那么函数指针该怎么写呢?


以数组指针为例:


数组指针示例:写一个指向 int arr[10] 数组的数组指针;


第一步:
(*p)    //先确定是一个指针
第二步:
(*p)[10]  //确定指向的是一个有10个元素的数组
第三步:
int(*p)[10] //确定该数组元素为int型
第四步:
int(*p)[10]=&arr;//将数组的地址赋值给数组指针
//或者int(*p)[10]=arr;


示例2:


函数指针:指向int add(int a,int b)


第一步:
(*p)      //先确定是一个指针
第二步:
(*p)(int,int) //确定指向的函数有两个参数
第三步:
int (*p)(int,int) //确定该函数的返回类型
第四步:
int (*p)(int,int)=&add;//将函数的地址赋值给函数指针
//等价于:int (*p)(int,int)=add;


1.2 函数指针应用


那么函数指针有什么用吗?


当然是用来调用函数了.


同样以数组指针为例:


🌰使用数组指针访问数组.


int main()
{
  int arr[10] = { 1,2,3,4,5 };
  int(*p)[10] = arr;
  for (int i = 0; i < 5; i++)
  {
    printf("%d ", ( * p)[i]);
  }
  printf("\n");
  return 0;
}


🌰使用函数指针调用函数


#include <stdio.h>
int add(int a,int b)
{
  return a + b;
}
int main()
{
  int a = 2, b = 3;
  int(*p1)(int, int) = &add;
  int(*p2)(int, int) = add;
  int ret1=add(a,b);
  int ret2=(*p1)(a, b);//写法一
  int ret3=p1(a, b);//写法2
  printf("ret1=%d\nret2=%d\nret3=%d",ret1,ret2,ret3);
  return 0;
}


运行结果:都能完成函数的调用


ret1=5


ret2=5


ret3=5


二、函数指针数组


函数指针数组实质用于存放函数指针的数组.


即数组的成员都是函数指针.


写法:以数组成员都是指向类似int add(int,int)的函数指针为例


1.先写出函数指针
(int) (*p)(int,int)
2.改成数组
(int) (*p[10])(int,int)//函数指针数组


题目:使用c语言制作简单的计算器.


要求,可以进行加减乘除运算.


//简易计算器
#include <stdio.h>
void menu()//菜单
{
  printf("作者:初阶牛\n");
  printf("  欢迎使用计算器:\n");
  printf("+-------------------------------+\n");
  printf("| 1.add   2.sub |\n");
  printf("| 3.mul   4.div |\n");
  printf("|   0.退出    |\n");
  printf("+-------------------------------+\n");
}
int add(int a, int b)//加法函数
{
  return a + b;
}
int sub(int a, int b)//减法函数
{
  return a - b;
}
int mul(int a, int b)//乘法函数
{
  return a * b;
}
int div(int a, int b)//除法函数
{
  return a / b;
}
int main()
{
  int x=0, y=0;
  int input = 1;
  int ret = 0;
  do
  {
    menu();//打印菜单
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("输入两个操作数:");
      scanf("%d %d", &x, &y);
      ret = add(x, y);
      printf("ret = %d\n", ret);
      break;
    case 2:
      printf("输入两个操作数:");
      scanf("%d %d", &x, &y);
      ret = sub(x, y);
      printf("ret = %d\n", ret);
      break;
    case 3:
      printf("输入两个操作数:");
      scanf("%d %d", &x, &y);
      ret = mul(x, y);
      printf("ret = %d\n", ret);
      break;
    case 4:
      printf("输入两个操作数:");
      scanf("%d %d", &x, &y);
      ret = div(x, y);
      printf("ret = %d\n", ret);
      break;
    case 0:
      printf("退出计算器\n");
      break;
    default:
      printf("很遗憾,并没有这个选项:\n");
      break;
    }
  } while (input);
  return 0;
}


对于上面的代码,我们可以使用函数指针来简化.


感受一下函数的指针的魅力吧!


#include <stdio.h>
void menu()
{
  printf("作者:初阶牛\n");
  printf("  欢迎使用计算器:\n");
  printf("+-------------------------------+\n");
  printf("| 1.add   2.sub |\n");
  printf("| 3.mul   4.div |\n");
  printf("|   0.退出    |\n");
  printf("+-------------------------------+\n");
}
int add(int a, int b)//加法函数
{
  return a + b;
}
int sub(int a, int b)//减法函数
{
  return a - b;
}
int mul(int a, int b)//乘法函数
{
  return a * b;
}
int div(int a, int b)//除法函数
{
  return a / b;
}
int main()
{
  int x = 0, y = 0;
  int input = 1;
  int ret = 0;
  int(*arr[5])(int, int)={0,add,sub,mul,div};//使用函数指针数组
  do
  {
    menu();
    scanf("%d", &input);
    if (input > 0 && input < 5)
    {
      printf("输入两个操作数:");
      scanf("%d %d", &x, &y);
      ret=arr[input](x,y);//利用数组下标调用相应的函数
      printf("ret = %d\n", ret);
    }
    else if (input == 0)
    {
      printf("退出计算器\n");
      break;
    }
    else
    {
      printf("很遗憾,并没有这个选项:\n");
      break;
    }
  } while (input);
  return 0;
}


三、函数指针数组指针


函数指针数组指针:


指向一个数组.该数组的成员都是函数指针.


写法:


1.先写出函数指针
char* (*p)(const int, double, char*);
2.改成函数指针数组
char* (*pp[3])(const int, double, char*);
3.最后写成函数指针数组指针
  char* (*(*ppp)[3])(const int, double, char*);


可以通过函数指针p调用函数,


也可以通过函数指针数组的元素,pp[0]调用函数.


最后,可以通过(*ppp)找到函数指针数组,(*ppp)[0]调用函数.


示例:


char* test(const int a, double b, char* c)
{
  char* ret = "AAABBBCCCDDD\n";
  return ret;
}
#include <stdio.h>
int main()
{
  //函数指针
  char* (*p)(const int, double, char*)=test;
  //函数指针数组
  char* (*pp[3])(const int, double, char*);
  pp[0] = test;
  //函数指针数组指针
  char* (*(*ppp)[3])(const int, double, char*)=&pp;
  printf("%s", test(0,0,0));
  printf("%s", p(0, 0, 0));
  printf("%s", pp[0](0, 0, 0));
  printf("%s", (*ppp)[0](0, 0, 0));
  return;
}


四、回调函数


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


大家还记得冒泡排序吗?


但是冒泡排序只能排序整形,而qsort函数,内部采用快速排序,可以排序各种类型的数据,接下来展示qsort排序部分类型的方法.


示例:qsort函数部分应用


分别将元素比较方法int_cmp和char_cmp的指针(地址) 传给 qsot函数.由qsort函数调用这些比较函数.


#include <stdlib.h>
#include <stdio.h>
int int_cmp(void* e1, void* e2)//整形元素排序方法
{
  return *(int*)e1 - *(int*)e2;
}
int char_cmp(void* e1, void* e2)//字符型元素排序方法
{
  return (*(char*)e1) - (*(char*)e2);
}
int main()
{
  int arr1[10] = { 4,5,1,8,9,2,10,3,7,6 };
  char arr2[] = "fbadegc";
  int sz1 = sizeof(arr1) / sizeof(arr1[0]);
  int sz2 = sizeof(arr2) / sizeof(arr2[0]);
  qsort(arr1,sz1,sizeof(arr1[0]),int_cmp);
  for (int i=0; i < sz1; i++)
  {
    printf("%d ", arr1[i]);
  }
  printf("\n");
  qsort(arr2, sz2, sizeof(arr2[0]), char_cmp);
  for (int i = 0; i < sz2; i++)
  {
    printf("%c ", arr2[i]);
  }
  printf("%s", arr2);
  return 0;
}


运行结果:


1 2 3 4 5 6 7 8 9 10


a b c d e f g

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