数组指针
int main(void)
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
&a;
return 0;
}
数组的指针,整个数组的首地址,a[10] 40个字节的首字节的地址
int main(void)
{
int a[10] = {1,2,3,4,5,6,7,8,9,0}
int *p;
p = &a; // ❌ 基类型不同 整型/一维整型数组
}
int (*p)[10];
p = &a; //正确
printf("%p\n",p);
printf("%p\n",p + 1); //二者差sizeof(基类型) 40个字节
a <=> &a[0] //数组的首元素的地址
&a<=> //数组的首字节的地址
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4] = NULL;
p = a;
// *(p + 1) < = > p[1] a[1] int*
a[i][j] < = > *(*(a + i) + j)
int main(void)
{
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
printf("%d\n",*((int*)(a + 3) - 3));
}
值为10
二维数组作为函数参数,形参为指向数组的指针
动态内存分配
如果用就开,用完了就销毁
指针函数 ,是函数,返回值是指针
int main(void)
{
char *p = malloc(10);
return 0;
}
int main(void)
{
int n = 10,i;
int *p = NULL; //防止为野指针
p = malloc(n * sizeof(int));
if(p != NULL)
{
for(i = 0;i < n;++i)
{
p[i] = fib(i + i);
}
for(i = 0;i < n;++i)
{
printf("%d\n",p[i]);
}
free(p); //销毁空间
p = NULL; //置空
}
}
内存泄漏:malloc申请了空间,但是没有free销毁空间
扩容:malloc 一次申请空间一定是连续的,两次申请空间一定不是连续的
在使用返回值是指针的时候,需要注意的问题:
返回值是指针的函数不能返回局部变量的地址 (局部变量被销毁,成为野指针)
可以返回全局变量,static修饰的局部变量,自身传入的指针变量(实现对变量的间接访问)
函数指针
指针变量保存函数的入口地址
函数的函数名即为函数的入口地址
int add(int a,int b)
{
return a + b;
}
int sub(int a,int b)
{
return a - b;
}
void fn(void)
{
}
int main(void)
{
int (*p)(int a,int b) = NULL;
p = add;
return 0;
}
指针变量p可以指向add sub
类型匹配
设计函数指针的目的是降低程序的耦合性
运用:
回调函数
int div3(int n)
{
return n % 3 == 0 || n % 5 == 0;
}
void printArrary1(int *a,int len,int (*pfn)(int))
{
int i;
for(i = 0;i < len;++i)
{
if(pfn(a[i]) != 0)
{
printf("%d\n",a[i]);
}
}
}
int main(void)
{
short a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int len = sizeof(a) / sizeof(*a);
printArrary1(a,len,div3);
return 0;
}
比较大小
int shortcmp(const void *p1,const void *p2)
{
short *q1 = (short *)p1;
short *q2 = (short *)p2;
if(*q1 > *q2)
{
return 1;
}
else if(*q1 == *q2)
{
return 0;
}
else
{
return -1;
}
}
int main(void)
{
short a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int len = sizeof(a) / sizeof(*a);
int i;
qsort(a,len,sizeof(*a),shortcmp);
for(i = 0;i < len;++i)
{
printf("%d\n",a[i]);
}
return 0;
}