目录
10.3指针进阶
10.3.1数组指针
10.3.2指针数组
10.3.3函数指针
10.3.4指针函数
10.3.5函数指针的实际应用案例qsort函数:
10.3指针进阶
10.3.1数组指针
是指针 --- 指向对象的类型是 数组 int [3]
数组指针一般用于指向二维数组里面的一行, --- 行指针,存储行地址
数组指针定义:
数据类型 (* 指针名)[元素个数];
int a[2][4] = {{1,3,4,5},{6,7,8,9}
};// 定义一个数组指针指向 第0行。 int [4]
int (*p)[4]; // 4 或者 8 指针名:p
指针类型:int (*)[4]
指针指向对象类型: int[4]p = a;// 分析:
// p + i ---- i行的行地址
// *(p+i) ---- i行0列的 列地址
// *(p+i)+j ---- i行j列的地址 // 空间列地址:*(p+i)+j &a[i][j]
// 空间列名称:*(*(p+i)+j) a[i][j]int i, j;for (i = 0; i < 2; i++)
{for (j = 0; j < 4; j++){printf ("%d ", *(*(p + i) + j));}printf ("\n");
}注意区分: 二维数组的地址偏移 行地址偏移 列地址的偏移 -- 类型不一样使用就不一样
//#include<stdio.h>
//
//int main(void)
//{
// int a[2][4] = {
// {1,3,4,5},
// {6,7,8,9}
// };
//
// // 定义数组指针指向a[0]
// int (*p)[4] = a;
//
// printf("%p %p\n",&a,&a+1);
// printf("%p %p\n",p,p+1); // 行地址
// printf("%p %p\n",*(p+0),*(p+1)); // 每一行的首列的地址
// printf("%p %p\n",*(p+0)+1,*(p+1)+1); // 列地址的偏移
//
// return 0;
//}
数组指针应用场景:
需要将二维数组传递到函数内部使用。
void test (int (*p)[4], int row, int col)
{int i, j;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf ("%d ", *(*(p + i) + j));}printf ("\n");}
}int main ()
{int a[2][4] = {{1,3,4,5},{6,7,8,9}};int r = sizeof (a) / sizeof (a[0]);int c = sizeof (a[0]) / sizeof (a[0][0]);test (a, r, c); // 实参 是 &a[0] -- 行地址 ---- 形参和实参在类型上要一致,接收行地址用行指针。return 0;
}
总结:
数组指针 是一个 指针指向 二维数组的一行, 一般用于将一个二维数组传入到函数内部的时候用,形参设计成数组指针。
10.3.2指针数组
是数组 里面存储同种类型的指针。
指针数组定义:
指针类型 数组名[元素个数];
例子:
int a = 10;
int b = 20;// &a &b ---- int *// 定义一个数组用来存储 &a &b
int* arr[2];arr[0] = &a;
arr[1] = &b;int i;
for (i = 0; i < 2; i++)
{printf ("%d ", *(arr[i]));
}
总结:
数组指针:
行指针 -- 指向二维数组的一行 存储行地址
int (*p)[4]; // 4/8
和 二位数组的数组名用法类似
数据地址:* (p + i) + j
数据空间: * (*(p + i) + j)
场景:将二维数组传入到函数内部,形参设计成数组指针。
指针数组:
数组,里面存储同种类型的指针。
int* arr[2]; // 8 / 16
先按照数组[下标] 获取指针元素,在将指针元素按照指针使用。
10.3.3函数指针
是指针,指向对象类型是函数类型
(准备函数、定义函数指针、函数指针指向函数、函数指针定义函数)
函数指针的定义:
函数类型 *指针名;
#include<stdio.h>//test 是个函数,它的参数是函数指针,即p
void test (int (*p)(int, int),int a,int b)
{int res = p(a,b);printf ("%d \n", res);
}int add (int a,int b)
{return a + b;
}
int dis (int a, int b)
{return a - b;
}
int mul (int a, int b)
{return a * b;
}int main ()
{test (mul,6,9);return 0;
}
10.3.4指针函数
是函数,函数的返回值是指针类型,函数返回一个地址。
定义指针函数
指针类型 函数名(形参列表)
{函数体return 地址;
}
指针类型 变量名 = 调用函数(形参列表);
注意:指针函数返回的地址 不能是局部变量的地址
可以返回传入到函数内部的空间外部空间的地址 或者 动态内存申请的地址
错误案例
int *test()
{int n;return &n;
}
返回的地址在调用函数结束之后就被销毁了,还返回有啥用?
10.3.5函数指针的实际应用案例qsort函数:
qsort函数分析
qsort函数C语言编译器函数库自带的排序函数。
qsort 的函数原型是
void qsort(void*base,size_t num,size_t width,int(*compare)(const void*,const void*));
qsort函数包含在C 标准库 - <stdlib.h>中。
函数原型分析:
void qsort(void*base,size_t num,size_t width,int(*compare)(const void*,const void*));
函数名:qsort
返回值类型:void
形参列表:
void *base , 接收任意类型地址 --- 数组首元素的地址
size_t nitems, 接受整型数据 --- 数组中元素的个数
size_t size, 接受整型数据 --- 数组中每个元素所占字节数
int(*compare)(const void*,const void*) 函数指针 --- 接受函数地址 --- 比较两个元素的函数
函数指针指针名:compare
函数指针指向对象类型: int (const void*,const void *)
返回值 >0 就交换位置
返回值 <0 就
#include<stdio.h>
#include<stdlib.h>// 返回值 >0 就交换位置 // 从小到大
int cmp (const void* a, const void* b)
{return *((int*)a) - *((int*)b);
}int main (void)
{int a[] = { 3,5,19,5,4,2,79,5,4,6,7,8 };int len = sizeof (a) / sizeof (a[0]);qsort (a, len, sizeof (a[0]), cmp);int i;for (i = 0; i < len; i++){printf ("%d ", a[i]);}return 0;
}