目录
🍑🍑1.字符指针
🍑🍑 例题1
🍑🍑2.指针数组
🍑🍑例题2
🍑🍑 3.数组指针
🍑🍑 3.3 数组指针的使用
🍑🍑5.函数指针
🍑🍑 7.回调函数
前言:
这是指针的进阶,如果想入门指针的朋友可以关注我的另外一篇文章—c语言指针
坚持看完,一定会有很大的收获~~
那接下来—起航
1.字符指针
📃在讲解字符指针前,我先提一下怎么连续创建多个指针
连续创建多个指针的方法:
创建指针的正确打开方式:
//方案一,直接定义两次
int a,b;
int*a; int*b;
//方案二,采用typedef重定义
typedef int* pint
{
int a,b;
pint pa, pb;//此时就是定义int *pa与int *pb都是指针变量
return 0;
}
下面给出一个简单的代码:
char ch='w';
char* p=ch;
char* p="abcde";
🔒例题
判断下面代码是否相等
char arr1[] = "abcdef";
char arr2[] = "abcdef";
const char* str1 = "abcdef";
const char* str2 = "abcdef";
#include<stdio.h>//证明相等关系
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
const char* str1 = "abcdef";
const char* str2 = "abcdef";
if (arr1 == arr2)
printf("arr1==arr2\n");
else
printf("arr1!=arr2\n");
if (str1 == str2)
printf("str1==str2\n");
else
printf("str1!=str2\n");
return 0;
}
为什么arr1!=arr2; str1==str2
2.指针数组
int*arr[5];//整形指针数组
char*arr[5];//一级字符指针数组
char**arr[5];//二级字符指针数组
知道定义,那如何使用呢
例题
多组打印字符串
#include<stdio.h>
int main()//指针数组
{
char* arr[] = { "abcdef","ghi" ,"jklmn" };
//打印
int i = 0;
int sz = sizeof (arr) / sizeof (arr[0]);
for (i = 0; i < sz; i++)
{
printf("%s\n",arr[i]);
}
return 0;
}
打印的结果就是:
✨✨打印整形的数组
#include<stdio.h>
int main()
{
//打印整形数
int arr1[] = { 1, 2, 3, 4, 5};
int arr2[] = { 2, 3, 4, 5, 6};
int arr3[] = { 3, 4, 5, 6, 7};
int* arr[] = { arr1,arr2,arr3 };
int i = 0; int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d", arr[i][j]);
}
printf("\n");
}
return 0;
}
3.数组指针
3.1数组指针的定义
int *pint;//能够指向整形数据的指针
char *p;//能够指向字符数据的指针
char (*p)[10];能够指向数组的指针
3.2 &数组名与数组名
#include<stdio.h>
int main()
{
int arr[20] = { 0 };
printf("%p\n", arr);
printf("%p\n", arr+1);
printf("%p\n", &arr);
printf("%p\n", &arr+1);
return 0;
}
📃接下来在看一个代码
int *p[10];
int *(*pp)[10];
此时的int *p[10],p就是指针数组变量
int *(*pp)[10]这句的意思就是定义一个指针变量,什么指针?数组指针,而这个数组里的元素都是int*,有十个int*类型的数据。这就是数组指针~~
故arr在一般情况下都是这个数组首元素的地址,&arr就是整个数组的地址
3.3 数组指针的使用
说完数组指针的定义和使用规则,下面讲解数组指针的使用
给定三个数组,分别打印出他们的值
#include<stdio.h>
print(int (*p)[5],int r,int c)//此时的int (*p)[5]就是一个数组指针
{
int i = 0; int j = 0;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d", *(*(p+i) + j)); //*(p+i)就相当于拿到第一行的地址
}
printf("\n");
}
}
int main()
{
//打印数字
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr,3,5);
return 0;
}
打印的结果:
那下面来总结一下:
int *arr;
int *parr1[10];
int (*parr2)[10];
int(*parr3[10])[10]
4.数组与指针在函数里的传参
函数传参的前提就是形参与实参是对应的关系,也就是说实参是什么类型,那么形参也是相应的类型,比如说实参是数组,那形参就是数组,参数是指针,那么形参也是指针。
4.1 一维数组的传参
#include<stdio.h>
test(arr1[])
{}
test(arr1[10])//上面两种方法,实参是数组,用数组来接收,因为在函数中本身不创建空间,所以无论【】{} //中的值为多少,都能达到目的~
test(*arr1)
{} //前面我提到数组名就是首元素的地址,此时就把实参中的数组名当作首元素的地址,此时用指
//针来接收
test(*arr2[10])
{} //这里也跟第一二两个相同,也是数组传参,数组来接收
test(**arr2)
{} //这里采用二级指针来接收,实参是一级指针,那么一级指针的指针就可以用二级指针来接收
int main()
{
int arr1[10]={0};
int* arr2[10]={0};
test(arr1);
test(arr2);
return 0;
}
4.2 二维数组的传参
#include<stdio.h>
//通过数组
test(int arr[10][10]) //二级指针传参时以数组的形式,【】中的行可以省略,但是列不能省略
{} //列可以让系统知道一行有多少的元素,从而分配多少的空间,便于知道每一
//个元素的地址,故test(int arr[10][10])与test(int arr[][10])是可以
//进行传参的,但是test(int arr[][])显然是不可以的。
test(int arr[][])
{}
test(int arr[][10])
{}
//通过指针
test(int *arr)
{}
test(int (*arr)[10]) //我们知道实参传的是首元素的地址,这里的首元素的地址就是第一行元素的
{} //地址,也就是数组的地址,所以需要数组指针来接收
//故需要test(int (*arr)[10])来接收,而一级指针与二级指针显然是不可的
test(int** arr)
{}
int main()//二级指针传参
{
int arr[10][10] = { 0 };
test(arr);
return 0;
}
4.3 一级指针的传参
#include<stdio.h>
test(int *p)
{}
int main()
{
int a = 10;
int* par = &a;
int arr[10];
test(par);
test(arr);
test(*a); //当一级指针传参时,形参是指针,那么实参就可以用这三种方式传参
return 0;
}
4.4 二级指针的传参
#include<stdio.h> //当二级指针传参时,形参是二级指针,那实参有哪些方式呢
test(int** p)
{}
int main()
{
//二级指针传参
char a = 'w';
char* p = &a;
char** pp = &p;
char* arr[10] = { 0 };
test(&p); //通过一级指针p的取地址
test(pp); //通过二级指针传参,用二级指针来接收
test(arr); //通过char*()类型指针数组名来传递
return 0;
}
5.函数指针
数组指针就是数组的地址
那么函数指针也是存放函数地址
📌那问题是函数有指针吗
#include<stdio.h>
int Add(int x,int y)
{
int sum = 0;
sum = x + y;
}
int main()
{
//证明函数有地址
int a = 0;
int b = 0;
printf("%p", &Add);
printf("%p\n", Add);
//定义一个函数指针变量
int (*pf)(int,int)=&Add; //此时的pf就是函数的指针变量,用pf就可以调用函数
return 0; //括号中是参数的类型
}
调用这个函数:
#include<stdio.h>
int Add(int x,int y)
{
int sum = 0;
sum = x + y;
return sum;
}
int main()
{
int (*pf)(int,int) = &Add;
int ret1=(*pf)(2, 3); //括号别忘了
int ret2 = (pf)(2, 3);//这里的括号可以省略
printf("%d\n", ret1);
printf("%d\n", ret2);
return 0;
}
打印的结果:
6. 函数指针数组
#include<stdio.h>
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 Div(int x, int y)
{
return x / y;
}
int main()
{
//int (*pf1)(int, int)=&Add;
//int (*pf2)(int, int)=⋐
//int (*pf3)(int, int)=&Mul;
//int (*pf4)(int, int)=&Div;
int (*pfAdd[4])(int, int) = { &Add ,&Sub,&Mul,&Div };//数组指针可以很好的实现多次的定义
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d\n", *(pfAdd[i])(8, 4));
}
return 0;
}
通过简单的数组的调用,就可以实现加减乘除的运算,那函数指针数组有什么用呢
既然函数指针数组可以同时实现加减乘除,那当然可以实现一个计算器
用函数指针数组实现一个计算器
#include<stdio.h>
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 Div(int x, int y)
{
return x / y;
}
menu()
{
printf("*****************************************\n");
printf("******** 1.Add 2.Sub ***********\n");
printf("******** 3.Mul 4.Div ***********\n");
printf("******** 0.exit ***********\n");
printf("*****************************************\n");
}
int main()//用函数指针来实现一个计算器
{
int x = 0;
int y = 0;
int input = 0;
int ret = 0;
int (*pfArr[5])(int, int) = { 0, &Add ,& Sub,& Mul,& Div };
do
{
menu();
printf("请选择:>");
scanf_s("%d", &input);
if (input == 0)
{
printf("计算机以关闭");
}
else if (input >= 1 && input <= 4)
{
printf("请输入x与y:>");
scanf_s("%d %d", &x, &y);
ret = pfArr[input](x, y);
printf("%d\n", ret);
}
else
printf("选择错误");
} while (input);
return 0;
}
7.回调函数
📌📌回调函数就是通过函数指针调用的函数,如果把一个函数的指针(地址)当作参数,传给另一个函数,当这个函数调用所指的函数时,我们就说这是回调函数。
下面来用回调函数来实现上一次用函数指针数组实现的计算器
#include<stdio.h>
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 Div(int x, int y)
{
return x / y;
}
menu()
{
printf("*****************************************\n");
printf("******** 1.Add 2.Sub ***********\n");
printf("******** 3.Mul 4.Div ***********\n");
printf("******** 0.exit ***********\n");
printf("*****************************************\n");
}
void calc(int (*pf)(int, int))
{
int x = 0; int y = 0;
printf("请输入两个数:>");
scanf_s("%d %d", &x, &y);
int ret = pf( x, y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
printf("请选择:\n");
menu();
scanf_s("%d", &input);
switch(input)
{
case 1:
calc(Add);
break;
case 2:
calc(Sub);
break;
case 3:
calc(Mul);
break;
case 4:
calc(Div);
break;
case 0:
printf("退出计算器");
break;
default:
printf("选择错误");
break;
}
} while (input);
return 0;
}
结语:这一章,c语言的指针相关的知识就结束了
欢迎点赞收藏加关注,如若有问题可以提出来😁😁😁😁