1.数组指针
1.1定义及一维数组指针
指向数组的指针,如
int a[10] = {1,2,3,4,5,6,7,8,9,0};
&a;//指取占40个字节的数组a中首字节的地址,注意区分a<=>&a[0]指取占4个字节的a[0]的首字节地址,但它两的值都是一样的,基类型不同。
int *p; p = &a;是错误的,类型不同,p是int *型,而&a是指取长度为10的一维整形数组的首字节地址,所以正确的定义如下:
int (*p)[10];//此处的“()”不能省,省略后为int *p[10]指定义长度为10的存储int *的一维数组;即指针数组;
p = &a;
此处的p + 1按规则,加一个长度为10的int型一维数组,向后偏移10 * 4个字节。
1.2二维数组指针
a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4] = NULL;//定义指向长度为4的一维数组的指针
p = a;//p指向a[0],a<=>&a[0],取a[0]的首字节地址
p += 1;//p指向a[1]
*(p + 1)//a[1],类型为int *,即此处取的是a[1]首字节的地址
*(*(p + 1) + 2)//a[1][2] 即7
例子:*((int *)(a + 3) - 3),a指取a[0]的首字节地址,类型为一维数组的地址,所以加三是加上4 * 4 * 3个字节,即到了第a[3](越界),然后(int *)是强制类型转换,把一维数组的地址类型改为int *型,所以再减3,即减了3 * 4个字节,即到了a[2][2]的位置,即为10.
二维数组作为函数参数,形参为指向数组的值
二维数组的遍历
二维数组的逆序
二维数组边数求和
2.指针函数
函数返回值是指针,一般用在动态内存分配中
2.1malloc
void* malloc(size_t size) 括号内指内存大小,按字节算,调用时要加头文件#include<stdlib.h>,指返回内存空间首字节的地址(此处记为p),而且保证内存空间连续,内存空间开在栈区。
若没申请到内存空间,则返回NULL,所以可以用if(p != NULL)来判断是否申请到;
堆区没有自动销毁功能,所以要用free(p)来销毁空间,销毁后p就变成野指针,还要加上p = NULL;
内存泄漏:指不写free来销毁空间,则会一直占用空间,导致空间越用越少
2.2reallo
realloc(p, size_t size),p为上面的源指针,后面为新开内存空间的大小,即:
int *p = malloc(n * sizeof(int));
int *q = malloc(m * sizeof(int));
memcpy(q, p, n*sizeof(int));
free(p);
p = q;
2.3
返回值为指针的函数,不能返回局部变量的地址;
可以加上static,或使用全局变量g_函数名,或传进去的变量。
3.函数指针
保存函数的入口地址,指针指向函数
函数名,即函数第一条指令所在的地址
保存函数入口地址:不能直接p = 函数名,基类型不匹配
int (*p)(int a,int b) 指针p可以指向含两个整形作为参数,返回值为整形的函数(a,b可以省略),此时就能 p = 函数名,例子
调用时直接p(a, b),不用写成(*p)(a,b),降低程序的耦合性
qsort(变量首字节地址,多少个元素,一个元素多少字节,比较函数)
此比较函数看你比较值的符号判断大小,同strcmp,s1 > s2,return 1,表示s1比s2大。