一、字符指针
字符指针char*两种使用方法:
//用法一:指向一个字符变量
char ch = 'a';
char* pc = &ch;
//用法二:指向一个字符串首地址
const char* p = "abcde";
//注意p存储的是字符串的首地址,也就是字符'a'的地址。
二、指针数组
指针数组是一个数组,用来存放指针:
int* arr[5];//存储的是整型指针
char* arr2[5];//存储的是字符型指针
char** arr3[5];//存储的是字符型二级指针
……
三、数组指针
1. 数组指针的定义
数组指针是指针,它指向的是一个数组:
//数组指针,指向的是一个数组
int (*p1)[10];//p1指向的数组有10个元素,每个元素都是int型
char (*p2)[5];
……
2. &数组名和数组名
数组名通常都是表示数组首元素的地址,但是有两个例外:
(1)sizeof(数组名):表示整个数组,计算的是整个数组的大小;
(2)&数组名:表示整个数组,获取整个数组的地址(地址值与数组首元素地址值相同,但是意义不同)。
例如:
①此时arr和&arr[0]与&arr的地址值相同,但是它们的意义不同:arr和&arr[0]表示数组首元素的地址;&arr表示整个数组的地址,类型为int[5]*,是一个数组指针。
②arr+1和&arr[0]+1都表示数组首元素地址偏移一个单位,其类型为int*,偏移4个字节;而&arr+1表示整个数组地址偏移一个单位,其类型为int[5]*,偏移一个数组大小,即20字节。
四、数组参数、指针参数
1. 一维数组传参
2. 二维数组传参
3.一级指针传参
int func(int* p, int size) {
for (int i = 0; i < size; ++i) {
printf("%d ", p[i]);
}
}
int main() {
int arr[5] = { 1,2,3,4,5 };
int* p = arr;
int size = sizeof(arr) / sizeof(int);
func(p, size);
return 0;
}
4. 二级指针传参
int func(int** p) {
printf("%d\n", **p);
}
int main() {
int a = 10;
int* p = &a;
int** pp = &p;
func(pp);
return 0;
}
对于参数传递,其实只需要我们做好分析,保证传递的类型和接收的类型一致就可以。
五、函数指针
指向函数的指针,就叫做函数指针:
注意:取地址函数名,和函数名,都是得到函数的地址。
函数指针的简单使用:
六、函数指针数组
arr就是一个函数指针数组,大小为3,存储的是int (*)(int,int)类型的元素。
七、指向函数指针数组的指针
pp此时就是指向函数指针数组的指针:pp是一个指针,指向的是一个大小为3的数组,数组存储的元素是int (*)(int,int)类型的元素。
八、回调函数
回调函数就是一个通过函数指针调用的函数:当我们把函数的指针(地址)作为参数传递给另一个函数,然后这个指针被用来调用其所指向的函数时,就认为这是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时,由另一方调用,用于对该事件或条件进行响应。