12 指针
12.1 void*指针
void指针可以接受任意类型的指针变量
12.2 类型确定
右左法则:第一次开始阅读声明的时候,必须从变量开始,而不是从最内部的括号 开始,向右看,碰到一个括号(只是说括号,中括号不算)就调转阅读的方向,括号 内的分析完时就跳出括号,这样继续,直到整个声明被分析完。
12.3 指向数组的指针
int* p[5];
int(*p)[5] //p是一个指向拥有5个元素的数组的指针(int [5])
int x[5]={0,1,2,3,4}; //x代表首元素指针,&x代表指向int[5]的指针
p=&x; //必须把数组的地址赋给p,因为p是一个指向数组的指针,不能直接
p=x; &x[0]只是第一个元素的地址,是int*类型 , &x的类型是int(*) [5]类型
int* p=x;//代替指向数组的指针,这样比较方便 ,指向数组的指针不方便
int z[8][5] int (*p)[5]
数组名z表示z[0]的地址,是一个int[5]的地址 ,所以可以p=z;
12.4 函数指针
int* f(char) //f是一个函数,返回int*类型
int (*p)(char) //p是一个指向函数的指针
printf("&main=%p\n",&main); //函数的地址
int (*q)(); //q是一个指向形参任意,返回int的函数
q=&main; //也可以q=main;//函数名本身就是地址
p=&main //这样不可以,参数类型不一致
对函数地址只能进行赋值和调用,算术运算不可以 函数的指针必须和它指向的函数有相同的返回值和参数,指针函数的参数和返回 值都可以是void
12.5 函数指针做形参
void foreach(int a[],int n,void (*fp)(int*));
//通用函数:通过将函数指针作为形参传入,完成对不同函数的调用,类似C#委托处理
12.6 结构体的指针
结构体的指针可以通过指针p->year直接访问结构体成员, 也可以(*p).year访问结构体成员
12.7 二级指针
例如链表中获取指向下个节点的next指针,将其封装为函数时,必须返回二级指针或者next指针的引用。具体代码参看数据结构与算法(DS&A)