🚀前言
基于阿辉前两篇博客指针的基础篇和进阶篇对于指针的了解,那么今天阿辉将为大家介绍C语言的指针剩下的部分,包括指针数组以及利用函数指针来实现简易计算器及typedef关键字,关注阿辉不迷路哦 😘 ,内容干货满满😋,接下来就跟着阿辉一起学习吧👊
🚀两段有趣的代码
以下两段代码出自于《C陷阱和缺陷》这本书,这两段代码有一定的难度,需要有一定的指针基础否则可能看不懂,看不懂的可以翻看阿辉前两篇关于指针的博客。
代码1
( *( void ( * )())0 )()
这段代码确实变态,铁子们别急,让我们分析一下:
1.首先,代码( *( void ( * )())0 )()
右边单独的括号()
很明显它是函数调用操作符,说明( *( void ( * )())0 )
这一大坨代表一个函数名
2.然后,void ( * )()
这一坨,铁子们这玩意不就是函数指针类型嘛,被指向函数返回类型是void
没有参数,void ( * )()
这玩意外面套个括号不就是(类型)
强制类型转换嘛
那这不就简单了,不就是把数字0强制转化成一个函数指针,然后解引用调用该函数
代码2
void (*signal(int , void(*)(int)))(int);
void (*signal(int , void(*)(int)))(int)
这一坨我们咋一看很懵,不过我要是把这个signal(int , void(*)(int))
拎出来铁子们肯定熟,这玩意怎么这么像函数声明,铁子们大胆点,你们看看void (*)(int)
这一部分不就是函数指针类型吗,这俩一结合不就是函数声明嘛
signal
是函数名,它的两个参数类一个是int
,一个是返回值为void
参数为int
的函数指针类型,然后signal
的返回类型也是一个返回值为void
参数为int
的函数指针类型
这里你可能会想这段码难写可读性还差,其实有解决方法,铁子们咱继续👇
✈️typedef关键字
通过typedef,可以为已有的数据类型定义一个新的名字,使得代码更易读、更易维护
语法格式为:
typedef 类型名 新类型名
例子:
typedef unsigned int size_t; size_t a; 对于size_t创建的变量a其实就是unsigned int类型的
对于指针类型,新类型名必须在*
右边
例子:
typedef int(*parr_t)[5]; typedef void(*pfun_t)(int); void (*signal(int , void(*)(int)))(int); 对于上面这段函数我们就可以这么写了 pfun_t signal(int , pfun_t); 可读性直接提升一大截
🚀指针数组
铁子们都知道,数组是自定义类型,前面咱们学了指针的一系列类型,这不咱们数组又添一个大家族——指针数组,指针数组顾名思义是存放指针的数组
指针数组的创建
type* name[const]; name是数组名 const是常量给定数组大小 type*是数组的类型
注意 :这里要与数组指针区分开,由于[]
的优先级高于*
,所以type* name[const]中name
与[]
先结合表明name
是指针,而数组指针type (*name)[const]中(*name)
确保*
与name
先结合表明name
是指针
举个栗子👇
int* a1[10];//存放整型指针的指针数组 char* a2[10];//存放字符指针的指针数组 int(*a3[10])[5];//存放数组指针的数组指针数组 int(*a4[10])(int);//存放函数指针的函数指针数组
指针数组有什么用呢?铁子们不要急我们接着看👇
🚀简易计算器的实现
利用switch
来实现简易计算器
简易计算器的实现思路:
- 内置加减乘除四种运算
- 打印菜单供用户选择运算方式以及退出计算器
- 输入待计算的数字
- 输出计算结果
#include <stdio.h> void menu() { 打印菜单 printf("*************************\n"); printf("**** 1:add 2:sub ***\n"); printf("**** 3:mul 4:div ***\n"); printf("**** 0:exit .... ***\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, y; int input = 1; int ret = 0; do { menu(); 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; }
上面的这段利用switch
实现的代码,有大量重复的元素导致代码极为臃肿,而且对于后期代码的维护也是极为不便,这里我们观察发现add,sub,mul,div
这四个函数有着同样的参数以及返回类型,这有什么用呢?铁子们我们接着看
我们完全可以,创建一个函数指针数组来存放他们
int (*a[])(int,int) = {add,sub,mul,div};
有了这个函数指针数组,我们只需要输入下标便可以通过a[input](x,y)
来调用函数,但是下标并没有与菜单对应起来,很简单仅需要在数组里面添一个NULL
就行int (*a[])(int,int) = {NULL,add,sub,mul,div}
然后一堆的switch case
语句简化成:
if (input == 0) { printf("退出计算器\n"); } else if (input >= 1 && input <= 4) { printf("请输入两个操作数:"); scanf("%d %d", &x, &y); ret = pfArr[input](x, y); printf("%d\n", ret); } else { printf("选择错误,重新选择\n"); }
不得不说设计C语言的人真的是厉害,后面如果要添加其他运算仅仅只用添函数改一下菜单以及把函数名加到数组里面就行了,绝真的绝!!!
到这里,阿辉今天对于C语言中指针部分的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹