C语言 指针(7)

目录

1.函数指针变量

2.函数指针数组

3.转移表


1.函数指针变量

1.1函数指针变量的创建

什么是函数指针变量呢?

根据前面学习整型指针,数组指针的时候,我们的类比关系,我们不难得出结论:

函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数的。

那么函数是否有地址呢?

我们做个测试:

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

输出结果如下:

cs 复制代码
1. test:  005913CA
2. &test: 005913CA

确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名

的方式获得函数的地址。

如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指

针非常类似。如下:

cs 复制代码
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(*pf3)(int x, int y) = &Add; //x和y写上或者省略都是可以的

函数指针类型解析:

cs 复制代码
int     (*pf3)   (int x, int y)
|       |        |
|       |        |-- pf3指向函数的参数类型和个数的交代
|       |
|       |-- 函数指针变量名
|
|-- pf3指向函数的返回类型
int (*) (int x, int y) //pf3函数指针变量的类型

1.2函数指针变量的使用

通过函数指针调用指针指向的函数

cs 复制代码
#include <stdio.h>
int Add(int x, int y) {
    return x + y;
}
int main() {
    int(*pf3)(int, int) = Add;
    printf("%d\n", (*pf3)(2, 3));
    printf("%d\n", pf3(3, 5));
    return 0;
}

输出结果:

cs 复制代码
1. 5
2. 8

1.3 typedef关键字

typedef 是用来给类型重命名的,可以把复杂的类型变得简单。

比如,觉得 unsigned int 写起来麻烦,要是能写成uint 就方便多了,那就可以这样用:

cs 复制代码
typedef unsigned int uint; 
//把unsigned int 重命名成uint

指针类型也能重命名,比如把int* 重命名成ptr_t,像这样:

cs 复制代码
typedef int* ptr_t;

不过对于数组指针和函数指针,重命名有点不一样。

比如有个数组指针类型 int(*)[5] ,要把它重命名成parr_t,就得这么写:

cs 复制代码
typedef int(*parr_t)[5]; 
//新的类型名必须在*的右边

函数指针类型的重命名也是一样的,比如,将void(*)(int) 类型重命名为pf_t,就可以这样写:

cs 复制代码
typedef void(*pfun_t)(int); //新的类型名必须在*的右边

2.函数指针数组

数组是一个存放相同类型数据的存储空间,我们已经学习了指针数组,比如:

cs 复制代码
int * arr[10]; 
//数组的每个元素是int*

那要把函数的地址存到一个数组中,那个数组就叫函数指针数组,那函数指针的数组如何定义呢?

cs 复制代码
int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3];

答案是: parr1

parr1 先和 [] 结合,说明 parr1 是数组,数组的内容是什么呢?

是 int (*)() 类型的函数指针。

3.转移表

函数指针数组的用途: 转移表

举例:计算器的一般实现

cs 复制代码
#include <stdio.h>
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, y;
    int input = 1;
    int ret = 0;
    do
    {
        printf("********************\n");
        printf("  1:add        2:sub \n");
        printf("  3:mul        4:div \n");
        printf("  0:exit              \n");
        printf("********************\n");
        printf("请选择: ");
        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;
}

代码解释 :

(1)头文件的引入:

cs 复制代码
#include <stdio.h>

#include <stdio.h> 指令用于引入标准输入输出头文件,该文件包含了 printf 、 scanf 等输入输

出函数的声明,使得程序能够进行输入输出操作。

(2)函数定义:

cs 复制代码
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;
}

这里定义了四个函数,分别是 add(加法)、sub (减法)、mul (乘法)、div (除法)。每

个函数都接收两个 int 类型的参数,并根据相应的运算规则返回计算结果。

(3)main函数:

cs 复制代码
int main()
{
    int x, y;
    int input = 1;
    int ret = 0;

- int x, y; 声明了两个整型变量 x 和 y ,用于存储用户输入的操作数。

- int input = 1; 声明并初始化了变量 input ,用于存储用户选择的操作选项,初始值设为 1 是为

了确保 do - while 循环至少执行一次。

- int ret = 0; 声明并初始化了变量 ret ,用于存储运算结果,初始值为 0 。

(4)do-while循环

cs 复制代码
    do
    {
        printf("********************\n");
        printf("  1:add        2:sub \n");
        printf("  3:mul        4:div \n");
        printf("  0:exit              \n");
        printf("********************\n");
        printf("请选择: ");
        scanf("%d", &input);
  • do - while 循环保证了循环体至少执行一次。

  • 循环体中,首先通过 printf 函数打印出操作选项菜单,提示用户进行选择。然后使用 scanf 函

数读取用户输入的整数,并存储到 input 变量中。

(5)switch语句:

cs 复制代码
        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);
  • switch 语句根据 input 的值来执行不同的分支:

  • case 1 :当用户选择 1 时,提示用户输入两个操作数,然后使用 scanf 读取,再调用 add 函

数进行加法运算,将结果存储在 ret 中,并打印出结果。

  • case 2 :与 case 1 类似,调用 sub 函数进行减法运算。

  • case 3 :调用 mul 函数进行乘法运算。

  • case 4 :调用 div 函数进行除法运算。不过这里没有对除数为 0 的情况进行处理,如果用户

输入 0 作为除数,程序会产生未定义行为。

  • case 0 :当用户选择 0 时,打印"退出程序",此时 input 的值为 0 , do - while 循环条件不

满足,程序结束。

  • default :当用户输入的不是 0 - 4 之间的数字时,打印"选择错误"。

  • do - while 循环的条件是 input ,只要 input 不为 0 ,循环就会继续执行,用户可以不断进行操作选择。

(6)函数返回:

cs 复制代码
    return 0;
}

main 函数返回 0 ,表示程序正常结束。在C语言中, main 函数返回 0 通常用于向操作系统表

明程序执行成功。

希望大家能够好好理解转移表这块的代码,感谢大家的观看!

相关推荐
hongyanwin3 小时前
cmake qt 项目编译(win)
开发语言·qt
元亓亓亓5 小时前
Java后端开发day42--IO流(二)--字符集&字符流
java·开发语言
JANYI20186 小时前
在c++中老是碰到string&,这是什么意思?
开发语言·c++
一支闲人6 小时前
C语言初阶:函数的嵌套调用、链式访问、声明、定义、递归
c语言·c语言基础知识·适用于新手小白
passionSnail6 小时前
《MATLAB实战训练营:从入门到工业级应用》趣味入门篇-用声音合成玩音乐:MATLAB电子琴制作(超级趣味实践版)
开发语言·matlab
shenyan~6 小时前
关于Python:9. 深入理解Python运行机制
开发语言·python
天堂的恶魔9467 小时前
C++ - 仿 RabbitMQ 实现消息队列(1)(环境搭建)
开发语言·c++·rabbitmq
殇淋狱陌7 小时前
【Python】常用命令提示符
开发语言·python·虚拟环境
anqi277 小时前
在sheel中运行Spark
大数据·开发语言·分布式·后端·spark
VB.Net8 小时前
C# 综合示例 库存管理系统20 操作员管理(FormAdmin)
开发语言·数据库·c#