指针的认识:
int arr[5]:数组
int *arr[5]:指针数组 ->[]的优先级高于*
int **arr[5]:二级指针数组
int (*arr)[5]:数组指针
int (*arr[10])[5]:具有5个元素的数组指针的数组
一维数组传参:
void test(int arr[])
{}
void test(int arr[10]//不要把10写成20,100等
{}
void test(int *arr)
{}
int main()
{
int arr[10]={0};
test(arr);
}
void test2(int *arr[20])
{}
void test2(int **arr)
{}
int main()
{
int *arr2[20]={0};
test2(arr2);
}
二维数组传参:
void test(int arr[3][5])
{}
void test(int arr[][5])
{}
void test(int (*arr)[5])
{}
int main()
{
int arr[3][5]={0};//将降维成数组指针
test(arr);
}
总结:二位数组传参时第一个维度是被忽略的,因为对一个二维数组,可以不知道有多少行,但是必须知道一行有多少元素
还有最重要的三句话:
- 所有的数组都可看成一维数组
- 所有的数组传参时都要发生降维,降维成指针
- 都要降维成指向其内部元素类型的指针
下面的传参是错误的:
void test(int arr[][])
{}
void test(int *arr)
{}
void test(int *arr[5])//注意和void test(int (*arr)[5])的区别
{}
void test(int **arr)
{}
一级指针传参:
传的是地址
当一个函数的参数部分为一级指针时,可以接收的参数,例如:
void test1(int *p)
{}
在这个例子中,p可以接收一维数组,一级整形指针
void test2(char*p)
p可以接收字符数组,字符地址,字符串
二级指针传参:
当一个函数的参数部分为一级指针时,可以接收的参数有
- 指针数组
- 二级指针
- 一级指针的地址
任何变量,只要传参都要形成临时变量
再来看两个变态的例子:
(*(void(*)())0)()
这是函数调用,具体的分析如下:
- void(*)(),这是一个函数指针
- 数字前带()表强转,所以(void(*)())0,是将0强转为函数指针
- (*(void(*)())0)是对0号地址处进行解引用,取得0号地址的内容充当地址
- 函数后边加()表示函数调用
void(*signal(int,void(*)(int)))(int);
这是一个函数指针,分析:
- signal()是一个函数
- 函数带两个参数(int,void(*)(int)),一个整形,一个函数指针
- void(*signal())(int)返回值是一个void*和一个int,就是一个函数指针
指向函数指针数组的指针:
void (*pfun)(const char*):函数指针
void(*pfunArr[5])(const char* str):函数指针数组
void(*(*ppfunArr) [5])(const char *):指向函数指针数组的指针
回调函数:
把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数
可以节省调用方的时间