开发者

深入解析C++中函数指针及其数组、typedef关键字用法举例

目录
  • 一、函数指针变量的创建
    • 1、什么是函数指针变量?
    • 2、函数是否有地址?
    • 3、创建函数指针变量
    • 4、函数指针类型解析
  • 二、函数指针变量的使用
    • 三、两段有趣的代码
      • 1、解释(*(void (*)())0)();
      • 2、解释void (*signal(int, void(*)(int)))(int);
    • 四、typedef关键字
      • 1、基本用法
      • 2、对于数组指针和函数指针的重命名
      • 3、使用typedef简化代码void (*signal(int, void(*)(int)))(int);
    • 五、函数指针数组

      一、函数指针变量的创建

      1、什么是函数指针变量?

              类比整型指针和数组指针的概念,我们可以得出:函数指针变量是用来存放函数地址的变量,通过这个地址我们可以调用相应的函数。

      2、函数是否有地址?

      通过以下测试代码可以验证:

      #include <stdio.h>
      void test() {
          printf("hehe\n");
      }
      int main() {
          printf("test: %p\n", test);
          printf("&test: %p\n", &test);
          return 0;
      }

      输出结果:

      深入解析C++中函数指针及其数组、typedef关键字用法举例

              结果表明函数确实有地址,且函数名就是函数的地址,也可以通过&函数名的方式获取函数地址。(重点!!!)

      3、创建函数指针变量

      函数指针变量的声明语法与数组指针类似:

      void test() {
          printf("hehe\n");
      }
      // 两种等效的函数指针声明方式
      void (*pf1)() = &test;
      void (*pf2)() = test;
      int Add(int x, int y) {
          return x + y;
      }
      // 函数指针声明,参数名可省略
      int (*pf3)(int, int) = Add;
      int (*pf4)(int x, int y) = &Add;

      4、函数指针类型解析

      int (*pf3)(int x, int y)为例:int (*) (int x, int y) 为pf3函数指针变量的类型

      深入解析C++中函数指针及其数组、typedef关键字用法举例

      二、函数指针变量的使用

      通过函数指针调用函数的示例:

      #include <stdio.h>
      int Add(int x, int y) {
          return x + y;
      }
      int main() {
          int(*pf)(int, int) = Add;
          // 两种等效的调用方式
          printf("%d\n", (*pf)(2, 3));  // 显式解引用
          printf("%d\n", pf(3, 5));     // 隐式调用
          return 0;
      }

      输出结果:

      深入解析C++中函数指针及其数组、typedef关键字用法举例

      三、两段有趣的代码

      以下两段有趣的代码出自《C陷阱和缺陷》:

      1、解释(*(void (*)())0)();

      这段代码的功能是:调用位于内存地址0处的函数

      让我们逐步解析:

      • void (*)():这是一个函数指针类型,表示"指向一个没有参数且返回void的函数的指针"。
      • (void (*)())0:将整数值0强制转换为上述函数指针类型。这表示"把地址0当作一个函数的地址"。
      • *(void (*)())0:解引用这个函数指针,得到位于地址0处的函数。
      • (*(void (*)())0)():最后调用这个函数(通过函数指针调用)。

      实际意义:这段代码尝试调用内存地址0处的函数。在嵌入式系统中,这可能是调用复位向量或启动代码的方式。但在大多数现代操作系统中,这会引发段错误(segmentation fault),因为地址0通常是被保护的区域。

      2、解释void (编程客栈*signal(int, void(*)(int)))(int);

      这是一个函数声明,声明了名为signal的函数。让我们分解它:

      • 最内层:void(*)(int):这是一个函数指针类型,表示"指向一个接受int参数且返回void的函数的OXQmnJ指针"。
      • signal(int, void(*)(int)):signal是一个函数,它接受两个参数:一个int、一个上述类型的函数指针
      • 整个声明:void (*signal(int, void(*)(int)))(int):表示signal函数返回一个函数指针,这个指针指向"接受int参数且返回void的函数"。

      更易读的写法(使用typedef,下面会讲解):

      typedef void (*sighandler_t)(int);  // 定义函数指针类型
      sighandler_t signal(int signum, sighandler_t handler);

      实际意义:这是Unix/linux系统中用于设置信号处理器的标准函数声明。它:

      • 接受一个信号编号(int)和一个处理该信号的函数指针
      • 返回之前为该信号设置的处理函数指针

      四、typedef关键字

      typedef用于类型重命名,可以简化复杂类型的声明。

      1、基本用法

      typedef unsigned int uint;  // 将unsigned int重命名为uint
      typedef int* ptr_t;         // 将int*重命名为ptr_t

      2、对于数组指针和函数指针的重命名

      新的类型名必须在*的右边:

      typedef int(*parr_t)[5js];    // 将数组指针类型int(*)[5]重命名为parr_t
      typedef void(*pfun_t)(int); // 将函数指针类型void(*)(int)重命名为pfun_t

      3、使用typedef简化代码void (*signal(int, void(*)(int)))(int);

      typedef void(*pfun_t)(int);
      pfun_t signal(int, pfun_t);

      五、函数指针数组

      数组是存放相同类型数据的存储空间。我们已经学过指针数组:

      int *arr[10];  // 数组的每个元素是int*

      如果要存储函数地址,就需要使用函数指针数组。函数指针数组的定义方式:编程客栈

      int (*parr1[3])();   // 正确:包含3个函数指针的数组,每个指针指向返回int的无参函数

      下面是错误用法:

      int *parr2[3]();     // 错误:错误语法
      int (*)() parr3[3];  // 错误:错误语法

      解析parr1

      • parr1先与[]结合,说明它是一个数组
      • 数组的内容是int (*)()类型的函数指针

      函数指针数组常用于实现状态机或回调函php数机制,是C语言中一种强大的编程技术。

      到此这篇关于深入解析C++中函数指针及其数组、typedef关键字用法举例的文章就介绍到这了,更多相关C++函数指针 typedef关键字内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜