【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现1

简介: 【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现

前言

本小节,我们将继续学习C语言转移表,什么是回调函数,回调函数又是什么?qsort函数怎么使用,怎么理解处理,要注意的细节,当然qsort使用举例,最后我们进行qsort函数的模拟实现!文章干货满满,走起

一、转移表

C语言转移表是指根据一定条件,实现程序执行流程的跳转或转移的机制。

具体来说,C语言中实现转移表的主要方式有:

  1. goto语句:
    goto语句可以实现无条件跳转,直接跳转到指定标签所在的代码块
goto 标签名; 
• 1

例如:

goto label;
  1. switch语句:
    switch语句根据表达式的值,选择性地执行一个代码块。它实现了有条件跳转。
switch(表达式)
{
  case 常数表达式1:
    //语句
    break;

  case 常数表达式2:  
    //语句
    break;

  //其他case
  
  default:
   //语句
}
  1. continue语句:
    continue 用于跳过循环体剩余部分,直接跳转到循环条件判断语句。

例如:

for(i=0;i<10;i++)
{
  if(i==5)
    continue;
  printf("%d",i);
}
  1. break语句:
    break 用于跳出整个循环或switch语句。

例如:

for(i=0;i<10;i++)
{
  if(i==5)
    break;
  printf("%d",i);
} 
  1. return语句:
    return 用于从函数中返回。

例如:

int func()
{
  return 0;
}

拓展:longjmp()/setjmp():

setjmp()和longjmp()是C语言中的两个非常重要的函数,它们可以实现非局部跳转的功能。


setjmp()函数声明如下:

 int setjmp(jmp_buf env);

1

jmp_buf是可以保存环境信息的结构体。


setjmp()会将当前函数的执行环境信息保存到env中,并返回0。


然后程序可以正常执行。


当需要跳转时,调用longjmp(env, val);

  • longjmp()函数声明如下:
void longjmp(jmp_buf env, int val);

longjmp()第一个参数就是setjmp()保存的env。


它会将程序跳转回setjmp()后面要执行的代码。


但此时setjmp()会返回longjmp()第二个参数val,而不是0。

jmp_buf env是setjmp和longjmp函数用来保存环境信息的结构体变量。


jmp_buf是一个预定义的数据类型,它用来描述一个环境的状态。

env是一个jmp_buf类型的变量。

当调用setjmp(env)时,setjmp函数会将当前函数调用栈(包括函数参数、局部变量等环境信息)保存到env这个结构体变量中。

之后程序可以正常执行。

当需要非局部跳转时,调用longjmp(env, val)。longjmp函数第一个参数就是这个env。

longjmp通过env这个结构体,可以恢复到setjmp函数保存环境时的状态。实现一个“跳回”的效果。

小总结:

  • jmp_buf是一个结构体类型,它可以保存一个函数环境的状态信息。
  • env是一个此类型的变量,用于在setjmplongjmp之间传递环境信息。
  • setjmp函数把当前环境信息保存到env中。
  • longjmp函数通过env这个结构体,实现恢复到setjmp时的环境状态,从而实现非局部跳转。

哎!当然你可以把env可以看作是一个“传送令牌”,只要通过longjmp把令牌改了,他就重新传送到setjmp,然后继续执行,它连接setjmp和longjmp,使得longjmp能找到正确的环境信息进行跳转。


所以通过setjmp()/longjmp()就实现了一个非局部跳转:程序似乎"跳回"到setjmp()后面要执行的代码,但实际上环境已经发生了变化。这在异常处理等场景中很有用。

工作原理是:

setjmp()函数会保存当前函数调用栈(包括函数参数和局部变量等信息)的环境,并返回0。


之后程序可以正常执行。


当需要非局部跳转时,调用longjmp(),并将在setjmp()保存的环境作为参数传入。


这个时候程序就会跳转回setjmp()保存的环境,仿佛从setjmp()后面继续执行。但此时setjmp()会返回非0值。

setjmp()函数会保存当前函数调用栈(包括函数参数和局部变量等信息)的环境,并返回0。


之后程序可以正常执行。


举个例子

# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <setjmp.h>

jmp_buf env; //jmp_buf是一个预定义的数据类型,它用来描述一个环境的状态。
      //env是一个jmp_buf类型的变量。

void func()
{
  //设置跳转点
  int ret = setjmp(env);

  if (0 == ret)
  {
    //正常流程
    printf("In func()\n");

    //触发跳转
    longjmp(env, 1);
  }
  else
  {
    //跳转后流程
    printf("Jumped back to func()\n");
  }
}

int main()
{
  func();
  return 0;
}

程序执行流程:

  1. 主函数调用func()函数。
  2. func()内首先调用setjmp()设置跳转点env。由于setjmp()第一次调用会返回0,所以进入if块。

打印"In func()"信息。

调用longjmp(),触发非局部跳转。

程序跳转回setjmp()设置的环境env,此时setjmp()返回1。

执行else块内的代码,打印"Jumped back to func()"。

func()返回,主函数结束。

通过在函数内使用setjmp()/longjmp(),实现了从函数内非局部跳回函数外的功能。这与goto不同,可以实现跨函数的非顺序跳转。它常用于异常和错误处理等场景。

  1. C语言函数指针数组可以用来实现转移表。

具体来说:

  • 定义一个函数指针数组,元素类型为函数指针。
  • 每个数组元素都指向一个具体的函数。
  • 根据条件调用数组对应元素所指向的函数。

这与传统的switch语句实现转移的效果是一致的。

个简单的示例:

// 函数定义
void func1() 
{
  printf("func1\n");
}

void func2() 
{
  printf("func2\n"); 
}

// 主函数
int main() 
{

  // 函数指针数组
  void (*funcs[])(void) = 
  {
    func1, 
    func2
  };

  int id = 1; // 条件值

  // 根据条件调用数组元素函数
  funcs[id]();
  
  return 0;
}

void f

这样就实现了根据条件值动态调用不同函数的功能,相当于一个简单的转移表。

函数指针数组用于转移表的优点是:

  • 更灵活,可以在运行时动态添加/删除函数
  • 扩展性好,支持条件复杂情况下的多路径转移
  • 与传统switch语句相比代码更简洁清晰

所以总的来说,函数指针数组正是C语言实现转移表的一个很好的选择。它可以很好地替代switch语句实现更复杂的多路转移逻辑。

通过这个你可能不太能看出哪里能很好的替代switch语句,让我们来看一个典型的例子,实现一个计算器!!!


【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现2:https://developer.aliyun.com/article/1474741


相关文章
|
24天前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
44 4
|
2月前
|
存储 C语言 C++
如何通过指针作为函数参数来实现函数的返回多个值
在C语言中,可以通过将指针作为函数参数来实现函数返回多个值。调用函数时,传递变量的地址,函数内部通过修改指针所指向的内存来改变原变量的值,从而实现多值返回。
|
2月前
|
存储 搜索推荐 C语言
如何理解指针作为函数参数的输入和输出特性
指针作为函数参数时,可以实现输入和输出的双重功能。通过指针传递变量的地址,函数可以修改外部变量的值,实现输出;同时,指针本身也可以作为输入,传递初始值或状态。这种方式提高了函数的灵活性和效率。
|
2月前
|
C++
指针中的回调函数与qsort的深度理解与模拟
本文详细介绍了回调函数的概念及其在计算器简化中的应用,以及C++标准库函数qsort的原理和使用示例,包括冒泡排序的模拟实现。
21 1
|
2月前
利用指针函数
【10月更文挑战第2天】利用指针函数。
19 1
|
2月前
|
算法 搜索推荐 C语言
【C语言篇】深入理解指针4(模拟实现qsort函数)
【C语言篇】深入理解指针4(模拟实现qsort函数)
25 2
|
6月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
3月前
|
Linux
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
4月前
|
程序员 C语言
指针在函数参数和返回值中的使用
指针在函数参数和返回值中的使用
65 9
|
4月前
|
存储 搜索推荐 C语言
C语言中的指针函数:深入探索与应用
C语言中的指针函数:深入探索与应用