作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 作者主页:一个平凡而乐于分享的小比特的个人主页 文章收录专栏:C语言指针总结,C语言指针是C语言部分重难点,也是编程笔试和面试的重灾区,本专栏旨在总结C语言学习过程中的易错点,通过调试代码,分析原理,对指针有更清晰的理解 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
#include <stdio.h>
void test(int arr[])//用数组名接收,数组名为首元素地址
{}
void test(int arr[10])//和上面方式一样,只是定义了接收数组的大小
{}
void test(int *arr)//此处用指针来接收,数组名为首元素地址,因此相当于二级指针
{}
void test2(int *arr[20])//此处用指针数组来接收,此时数组大小也可以省略
{}
void test2(int **arr)//此处用二级指针接收
{}
int main()
{
int arr[10] = {0};//arr为整形数组,其中有10个元素
int *arr2[20] = {0};//arr2整形指针数组,其中有20个元素
test(arr);//数组名为数组首元素的地址
test2(arr2);//数组名为数组首元素的地址,arr2为指针数组首元素的地址,相当于二级指针
}以上传参都是正确的。
void test(int arr[3][5])//ok
{}
void test(int arr[][])//err,行可以省略,但列不能省略
{}
void test(int arr[][5])//ok
{}
void test(int *arr)//err,arr为整形指针,用来存放整形的地址,不能接受一维数组的地址
{}
void test(int (*arr)[5])//ok,数组指针,arr指向一个一维数组,数组含有5个元素,每个元素为整形
{}
void test(int **arr)//err,arr为二级指针,不能接受一维数组的地址
{}
int main()
{
int arr[3][5] = {0};//arr为首元素的地址(第一行的地址)
test(arr);
}总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。这样才方便运算。
当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
void test1(int* p)
{}
void test2(char* p)
{}
int main()
{
int a=10;
int* p1=&a;
test1(&a);//ok
test1(p1);//ok
char ch='W';
char* pc=&ch;
test2(&ch);//ok
test2(pc);//ok
return 0;
}当函数的参数为二级指针的时候,可以接收什么参数?
#include <stdio.h>
void test(int** ptr)
{
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int*p = &n;
int **pp = &p;
test(pp);
test(&p);
return 0;
}void test(char **p)
{}
int main()
{
char c = 'b';
char*pc = &c;
char**ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);//Ok
return 0;
}数组指针--是指向数组的指针
函数指针--是指向函数的指针--存放函数地址的一个指针
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
由此可以看出&函数名 和 函数名 都是函数的地址
那我们的函数的地址要想保存起来,怎么保存?下面我们看代码:
void test()
{
printf("hehe\n");
}
void (*pfun1)();
void *pfun2();首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。
接下来,让我们看一个有趣的代码:
代码1:
(*(void(*)())0)();//把0强制类型转换成:void(*)()函数指针类型-0就是一个函数的地址
//调用0地址处的该函数代码2:
void(*signal(int,void(*)(int)))(int);//signal是一个函数声明
//signal函数的参数有2个,第一个是int。第二个是函数指针,该函数指 针指向的函数的参数是int,返回类型是void
//signal函数的返回类型也是一个函数指针:该函数指针指向的函数的参 数是int,返回类型是void
将其简化:
typedef void(*pfun_t)(int);
pfun_t signal(int,pfun_t);数组是一个存放相同类型数据的存储空间,那要把函数的地址存放到一个数组中,那这个数组就叫函数指针数组
int(*parr1[10])();//ok
int *parr2[10]();//err,存在语法错误
int (*)()parr3[10];//err,应该将parr3数组放到第一个圆括号里面,参考第一种写法函数指针数组的应用:
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* arr[5];//指针数组
int(*pa)(int,int)=Add;//Sub/Mul/Div
int(*parr[4])(int,int)={Add,Sub,Mul,Div};//函数指针的数组
int i=0;
for(i=0;i<4;i++)
{
printf("%d\n",parr[i](2,3));
}
}到这里,本片博客就到这里了。希望大家看了我的讲解,还是要在编译器上实操一下,加深理解。能看明白,不一定会写,只有不断反刍,才能转换成自己的东西哦。