字符指针
将一个字符串赋给一个字符指针时,该字符串是常量字符串,无法被修改
因此如果定义多个字符指针,其值都是该字符串时,该字符串在内存空间仅有一份
(因为是常量字符串,一份就够了,才不会造成浪费)
指针都指向字符串首元素的地址
指针数组
int *arr[5] = {1,2,3,4,5}; //是个数组,存放的元素是指针类型
数组指针
int (*p) [5] = &arr; //是个指针,存放数组的地址(注意不是数组首元素的地址)
tips:还有sizeof(arr)的arr是数组地址的意思,其他情况arr都是指数组首元素的地址
注:该方式为二维数组指针传参的方式!
存储数组指针的数组
int (*arr[10]) [3]; //该数组能够存放10个数组指针
每个数组指针能够指向一个数组,数组3个元素,每个元素是int类型
一维数组传参形式
当数组为 int arr[10] = {0}; 时:
void test(int arr [ ]);
void test(int arr [10]);
void test(int *arr);
当数组为 int *arr[20] = {0}; 时:
void test(int *arr [20]);
void test(int **arr);
二维数组传参形式
void test(int arr [3][5]); //数组传参
void test(int arr [ ][5]); //数组传参
void test(int (*arr) [5]); //指针传参
一级指针传参形式
pa &a arr
二级指针传参形式
ppa &pa arr(数组类型为一级指针)
函数指针
返回值类型 (*pa) (参数类型1,参数类型2…) = &函数名
例如:int (*pa) (int int) = &test
pa = &ADD, *pa = ADD是常规理解,又因为ADD 和 &ADD的意思一样,所以pa == *pa,*是个摆设,写几颗都行!
函数调用三种写法
int ret = (*p)(3,5)
int ret = p (3,5)
int ret = ADD(3,5)
2个小例子
1) (*(void(*)() )0) ();
1.该语句为调用0地址处的函数
2.该函数无参,返回类型是void
void(*)() - 函数指针类型
(void(*)())0 - 对0进行强制类型转换,被解释为一个函数地址
*(void(*)())0 -对0地址进行了解引用操作,得到一个函数名
(*(void(*)())0)() - 调用用0地址处的函数
from:<c陷阱和缺陷>
2) void (*signal(int, void(*)(int)) ) (int);
1.该条语句是一个signal函数的声明
2.signal 和()先结合,说明siqnal是函数名
3.siqnal函数的第一个参数的类型是int,第二个参数的类型是函数指针
该函数指针,指向一个参数为int,返回类型是void的函数
4.signal函数的返回类型也是一个函数指针。该函数指针,指向一个参数为int,返回类型是void的函数
5.可用typedef- 对类型进行重定义,会更好理解
typedef void(*pfun_t)(int); //对void(*)(int)的函数指针类型重命名为pfun_t
//类似于无符号整型的重命名:typedef unsigned int uint;
pfun_t signal(int, pfun t); //将语句简化成这样明显更好理解!
函数指针数组
int(*p) (int, int): //函数指针
int(* p2[4]) (int, int): //函数指针的数组
int(*(*p3)[4]) (int, int)= &p2; //取出的是函数指针数组的地址
//p3就是一个指向 [函数指针的数组] 的指针
回调函数
回调函数就是一个通过函数指针调用的函数。如果你报把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
int calc(int (*pf) (int, int)) //函数指针接收函数地址(即传进来一个函数名,用函数指针来接收,
{ //这个计算函数会根据传进来的不同函数名来进行相应回调并做返回!)
int x = 0;
int y = 0;
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
return pf(x, y); //回调函数并返回
}
库函数:qsort() ---> 快速排序 (头文件为stdlib.h)
void qsort (void* base, //base中存放的是待排序数据中 第一个对象的地址
size_t num, //排序数据元素的个数
sipe_t size, //排序数据中一个元素的大小,单位是字节
int (*cmp)(const void*, const void*) ); //函数指针,是用来比较待排序数据中的2个元素的函数
//注意:这个比较函数还要自己定义!!!
//整条语句是个函数的声明
实例:我们可以自定义一个类似于qsort的冒泡排序函数,对各种类型的数组进行冒泡排序!