高端建站是什么,公司网站建设建设,如何修改模板网站,商业空间设计网站大全1.指针数组
指针数组表较简单#xff0c;类比整型数组#xff0c;字符数组#xff0c;整型数组里面的元素都是整型变量#xff0c;字符数组里面
的元素是字符类型#xff0c;那么指针数组就是数组里面的每个元素都是指针类型#xff0c;例如int*arr[5]就是一个
指针数…1.指针数组
指针数组表较简单类比整型数组字符数组整型数组里面的元素都是整型变量字符数组里面
的元素是字符类型那么指针数组就是数组里面的每个元素都是指针类型例如int*arr[5]就是一个
指针数组数组里面的元素都是int*的指针类型
2.数组指针
数组指针是什么如何使用我们回忆一下二维数组传参我们知道一维数组的传参例test函数
test(arr)参数arr是数组名就是数组首个元素的地址我们也可以使用数组接受也可以使用指针
指向首个元素的地址通过指针的移动打印数组的元素
同理二维数组传参例如arr[3][5],传递参数test(arr),arr是二维数组的名字但是不是设个元素的
地址而是首行元素的地址这个时候如果想要使用指针接受这个指针就应该是数组指针指向
的是一个数组还是拿这个3行5列数组举例对于二维数组我们可以这样理解把二维数组理解成
3个一维数组实际上传递进去的是第一行以为数组的地址有5个元素我们使用数组指针
int(*p)[5]进行接收这个数组指针表示指向5个元素每个元素的类型是int类型数组指针的名字
是p指针指针类型int(*)[5],指针的类型决定了对指针进行加一操作会跳过几个字节如果是普通的
整形指针数组加一就跳过4个字节但是这里的p指针的类型是int(*)p,所以加一会跳过5个元素
也就是20字节。
3.函数指针变量
我们知道数组名表示 数组首个元素的地址函数名同样表示函数的地址取地址数组名表示整个
数组的地址但是取地址函数名仍然是函数的地址和直接的函数名没有区别 图片里面int (*p)(int,int)就是定义函数指针这个函数指针的参数有2个都是int类型
这个函数的返回类型是int类型实际上在进行调用的时候加上星号只是为了表示他是函数指针
加上2个或者多个星号都不影响使用不加星号都是可以的通过打印结果也可以知道
看似即使没有函数指针我们也可以对函数进行使用实际上后续函数指针会发挥巨大作用
4.二段有趣的代码分析
1 (*(void (*)())0)();
这个里面的void(*)()是函数指针类型放在括号里面就是进行强制类型转换把0转换成函数指针类
型,0是个地址这里的星号同上是可以省略的调用0地址处的这个函数这里面的0仅仅是一
个地址这个函数指针没有参数传递的参数也是空的如果要调用100地址处的函数就是
100总言之这是一次函数的调用
2.void (*signal(int , void(*)(int)))(int);
这个里面的void*)int)也是函数指针变量参数int类型返回void类型signal是一个函数函
数的参数是int类型和函数指针类型去掉后是void(*)(int)还是一个函数指针类型也就是这个函
数的返回值是函数指针类型函数的声明只需要高数参数的类型可以不写名字可能初学者会问
可不可以写为void(*)(int) signal(int,void(*)(int),或许这样写更加清楚但是编译器不支持实质上
这个是函数的声明
5.typedef关键字的使用
上面的这个例子对于比较长的数据类型或者指针类型名字我们可以进行简化这个时候就有了
typedef关键字
typedef unsigned int ptr就是把unsigned int这个比较长的类型用ptr代替
我们定义unsigned int a10;就可以直接写为ptr a10,使得原来复杂代码简单化就是重新起名字
还例如指针类型也可以进行简化int*类型也可以这样简化typedef int* asd,就是简化后名字asd
int(*p)[5]是数组指针类型int(*)[5],也可以重新命名不是int(*)[5] ptr,需要写为typedef int(*ptr)[5]
ptr也是一种类型了平时的int(*p2)[5]arr(这里的p2就是指针变量就可以写为ptr p2arr,
函数指针类型重命名原来的 void *pf)(int)函数指针typedef void(*)(int) ptr;以后定义就可以
写作ptr p2add,这样定义函数指针类型
同样使用ptr重命名函数指针void (*signal(int , void(*)(int)))(int);就可以简化为
ptr signal(int,ptr),变得更加简单简洁高效。
typrdef int* ptr;就是关键字重命名
#define int* PTR就是遇到PTR使用int*替代ptr a相当于int*a,这样也可以简化
第一一个变量的时候两者无区别定义2个时候就有区别
ptr a,b;可以同时定义a,b都是int*类型
PTR a,b;不能同时定义a,b是int*类型只能定义a ,b还是默认的int 类型
由此可见使用重命名的时候尽量使用typedef,使用#define可能会出现问题。
6函数指针数组
1首先讲一下函数指针数组如何使用 每一个运算的法则都是函数指针因为他们的参数返回类型都是相同的所以我们可以放到
一个数组里面这个数组就叫做函数指针数组循环里面直接调用就可以了
函数指针数组就是在函数指针名字后面加上元素个数
2接下来讲一下函数指针数组如何使用以一个计算机的构建为例这个计算机可以实现
简单的四则运算下面是自定义函数和主函数的代码
下面的是函数
int add(int x, int y)
{return x y;
}
int sub(int x, int y)
{return x - y;
}
int mul(int x, int y)
{return x * y;
}
int divi(int x, int y)
{return x / y;
}
下面主函数(注意除法的自定义函数不能直接使用div本人亲测div和库函数里面的div冲突
void menu()
{printf(*****************************************\n);printf(**********1.add**************************\n);printf(**********2.sub**************************\n);printf(**********3.mul**************************\n);printf(**********4.divi**************************\n);printf(**********0.exit*************************\n);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do {menu();printf(请选择\n);scanf(%d, input);switch (input){case 1:printf(请输入2个数字\n);scanf(%d %d, x, y);ret add(x, y);printf(%d\n, ret);break;case 2:printf(请输入2个数字\n);scanf(%d %d, x, y);ret sub(x, y);printf(%d\n, ret);break;case 3:printf(请输入2个数字\n);scanf(%d %d, x, y);ret mul(x, y);printf(%d\n, ret);break;case 4:printf(请输入2个数字\n);scanf(%d %d, x, y);ret divi(x, y);printf(%d\n, ret);break;case 0:printf(退出计算器);break;default:printf(请重新选择\n);break;}} while (input);return 0;
}
思考分析简化 这个是一个普通的计算器只有加减乘除法则运算
这样看来每个case都要重复显示的有些冗余这个时候可以使用函数指针数组
int main()
{int input 0;int x 0;int y 0;int ret 0;int(*ptr[5])(int,int) {NULL,add,sub,mul,divi};do{menu();printf(请选择\n);scanf(%d, input);if (input 1 input 4){printf(请输入2个数字\n);scanf(%d %d, x, y);ret ptr[input](x, y);printf(%d\n, ret);}else if (input 0){printf(退出计算器\n);break;}else{printf(选择错误重新选择\n);}} while (input);return 0;
}
这个时候引入数组里面就是函数因为要使我们输入的input和数组元素的下标相对应
所以我们把第一个元素设置为NULL,这样我们选择哪个数字就可以找到对应函数地址使用这个
函数这样函数的下标就是1234了ptr[input]直接找到对应的地址使用这个函数
而且如果想要增加法则只需要增加数组元素就可以了如果不是用这种数组就需要
增加case语句里面的内容还是需要重复更加复杂函数指针数组的优势就体现了出来。