1.数组指针
▶数组指针的定义
指向整个数组的指针
int arr1[10] = {1,2,3,4,5,6,7,8,9,10}; //每个元素的类型是int
int (*p)[10] = &arr1; //数组指针,(*p)代表p是指针,p指向的类型是 int [10]
//arr2,arr3与arr1同样定义
int *d[3] = {arr1,arr2,arr3}; //指针数组,d[3]优先结合,代表是个数组,每个元素的类型是int*
int* (*pd)[3] = &d; //数组指针,指向的类型是 int* [3]
通俗讲,数组指针就是个指针,指针数组就是个数组。
存放指针的数组叫指针数组,那么存放数组指针的数组呢,怎样定义呢。
//与上面代码衔接
int (*m[3])[10] = {&arr1,&arr2,&arr3};
//m[3]表示是个数组,存放3个元素。
//拿掉m[3]后就是每个元素的类型int (* )[10],即每个元素是个数组指针。
▶数组指针的使用
数组指针p指向整个数组(p的类型为int (*)[10] ),解引用*p后等价为数组名arr1(arr1的类型为int [10] ),值为首元素地址,但是代表的是这个数组(*p与arr1等价)。
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int (*p)[10] = &arr1;
for(i=0; i<10; i++)
{
pritnf("%d ", *((*p)+i)); //与(*p)[i]等价
}
printf("\n");
printf("%d\n", sizeof(*p)); //*p等价于名字arr1,值为首元素地址,但是代表整个数组,所以为40
printf("%d\n", sizeof(p[0]); //同上
一维数组的数组名指向的是→第一个元素。
二维数组的数组名指向的是→整个第一行数组,数组名=第一行数组的地址。
数组指针也是指向→整个数组,所以二维数组也可以当做数组指针去使用。
int arr[2][3] = { 1,2,3,7,8,9 }; //二维数组名arr指向的对象及类型是 int [3]
printf("%d\n", *(*(arr + 1)+1)); //8
int (*p)[3] = arr; //指针p指向的类型是 int [3],与上等价(p和arr等价)
printf("%d\n", *(*(p+1)+1));
2.函数指针
void test()
printf("%p\n", test);
printf("%p\n", &test);
void (*p1)() = test; //函数指针
void (*p2)() = &test; //与上等价
//通过指针调用函数
(*p1)(); //不能写成*p1()
p1(); //不用解引用*也可,因为函数名本身就是指针
//所以解引用多少层都一样
(*test)();
(**p1)();
例,函数返回类型为函数指针:
void (*signal(int, void(*)(int)))(int);
//含义为void(*)(int) signal(int, void(*)(int)) 但是语法不允许这样写
//返回类型为void(*)(int)
typedef void(*pfun_t)(int);
//含义为typedef void(*)(int) pfun_t
//将这个函数指针类型重命名为pfun_t
pfun_t signal(int, void(*)(int))
存放函数指针的数组——函数指针数组
int Add(int x, int y);
int Sub(int x, int y);
int (*p[2])(int, int) = {Add, Sub}; //数组内元素类型必须相同
//通过数组使用函数
p[1](x, y);
3.回调函数
int add(int x, int y)
{ return x+y; }
int cal(int (*p)(int, int)) {
int x,y;
printf("输入两个数:");
scanf("%d %d", &x, &y);
//其他通用代码
return p(x,y); //这里就定义为回调函数
}
int main() {
int ret;
ret = cal(add);
return 0;
}
4.关于void类型指针
void类型指针可理解为无具体类型,可以存放任意类型指针,但是不能解引用和运算,除非强制类型转换。