目录
1.指针数组
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
指针数组的应用(可以模拟实现一个二维数组)
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int* parr[3] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0; i < 3; i++)
/*这里arr1下标为0,arr2下标为1,arr3下标为2*/
{
int j = 0; /*j表示arr1里面的数组,{1,2,3,4,5}*/
for (j = 0; j < 5; j++)
{
/*printf("%d ", parr[i][j]);*/
printf("%d ", *(parr[i] + j));
//parr[i]是首元素地址,也是1的地址。 这里+j,是加数组里面的地址,然后再解引用找到值
}
printf("\n");
}
}
2.数组指针
int(*p)[10]
*先与p结合,说明这是一个指针,指向大小为10的整形的数组,叫做数组指针
数组指针的使用可以在二维数组传参中用
void print(int(*p)[5], int row, int col)
//p是一个指针,指向大小为5的整形数组
{
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
/* p+i是指向第i行的
*(p+i)相当于拿到了第i行,也相当于第i行的数组名
数组名表示首元素的地址,*(p+i)就是第i行第一个元素的地址*/
printf("%d ", *(*(p + i) + j));
printf("%d ", p[i][j]); /*这两种写法一样*/
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr, 3, 5);
//数组名arr,表示首元素的地址
//但是二维数组的首元素是二维数组的第一行
//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
//可以数组指针来接收
return 0;
}
这两种写法一样
arr[i]=*(arr+i) //arr是首元素地址,往后找i的地址,解引用找到值
arr[i][j]=*(*(arr+i)+j)
画图来解释这几个的不同
3.对于二维数组传参
void test(int* arr)//ok? 不行,一级指针不行,因为传过去的是首元素的地址,相当于第一行的地址
{} // 一级指针是用来接收普通变量的地址的
void test(int* arr[5])//ok? 数组接收也不行,我传过去的是一个首元素地址,相当于第一行的地址,地址放在数组里面不行
{}
void test(int(*arr)[5])//ok? 这个可以,地址放在数组指针里面,数组指针是用来存放数组的地址的
{}
void test(int** arr)//ok? 不行, 二级指针更不行了,二级指针存放的是一级指针的地址
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
}
当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
void test(int* ptr)
{
}
int main()
{
int a = 10;
int* p = &a;
int arr[10];
test(p); //p可以传,p是个指针,指针就是地址
test(&a); //&a可以传,就是a的地址
test(arr); //数组可以传,相当于首元素地址
}
当函数参数为二级指针的时候,函数能接收什么参数呢
void test(char** p)
{
}
int main()
{
char c = 'b';
char* pc = &c;
char** ppc = &pc;
char* arr[10];
test(&pc);
//可以传1级指针变量的地址
test(ppc);
//可以传二级指针变量
test(arr);
//可以传指针数组, arr数组每个元素都是char *,数组名表示首元素地址,就是char * 的地址
// char* 的地址可以用char * *
return 0;
}
4.函数指针
int Add(int x, int y)
{
return x + y;
}
int main()
{
int arr[10];
int(*p)[10] = &arr;
/*数组指针,是用来存放数组的地址的*/
printf("%p\n",Add);
printf("%p\n",&Add);
//这俩打印出来的结果一样
//对于函数来说Add和&Add一模一样,这两种写法都可以
int(*pf)(int, int) = Add;
//函数指针,是用来存放函数的地址的
//pf与*结合是个指针,指向的是(),说明是个函数,里面的参数是int,int,返回类型是int
return 0;
}
函数指针使用
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
//这两种结果一样都可以写
void(*pf)() = test; //这也可以写成test
(*pf)(); //通过pf指针调用test函数
test();
pf(); //把*去掉也可以调用,这里的*不起作用
return 0;
}
5.函数指针数组
把函数的地址存到一个数组中,那这个数组就叫函数指针数组
![](https://i-blog.csdnimg.cn/blog_migrate/8acd0eb1ae44cbb0a8c5dee6cb8577dc.png)
6.回调函数
回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
void cale(int(*pf)(int,int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = pf(x, y);
//pf调用加法,加法就是回调函数,以此类推
printf("ret = %d\n", ret);
}
int main()
{
int input = 1;
do
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf("*************************\n");
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
cale(add);
case 2:
cale(sub);
case 3:
cale(mul);
case 4:
cale(div);
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
7.qsort库函数
(可以排序结构体,整形,浮点型等等)
基于快速排序算法实现的一个排序的函数
void qsort(void* base, //待排序数据的起始位置
size_t num, //数组的元素个数
size_t width, //一个元素的字节大小
int(*cmp)(const void* e1, const void* e2));
// 比较函数 e1,e2是带比较两个元素的地址
// int 返回值是>0 =0 <0
之前写的冒泡排序只能排序整形,而qsort可以排序各种类型等等
qsort排序整形
用qsort进行排序(整形)
int cmp_int(const void* e1, const void* e2)
{
//void*的指针是无确切类型的,不能直接解引用进行比较,可以强制类型转化进行比较
return *((int*)e1) - *((int*)e2);
//qsort默认是升序排序的,如果想降序,把e1,e2交换即可
}
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof arr / sizeof arr[0];
qsort(arr, sz, sizeof(arr[0]), cmp_int);
print(arr, sz);
return 0;
}
qsort排序结构体
#include<string.h>
#include<stdlib.h>
int cmp_Stu_age(const void*e1, const void* e2)
{
//结构体类型要强转成结构体
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_Stu_name(const void* e1, const void* e2)
{
//字符串的比较不能直接相减,要用strcmp函数
return strcmp(((struct Stu*)e1), ((struct Stu*)e2));
}
struct Stu
{
char name[20];
int age;
double score;
};
void test()
{
struct Stu arr[3] = { {"zhangsan",60,90.0},{"wangwu",20,50.0},{"lisi,40,70.0"} };
int sz = sizeof arr / sizeof arr[0];
/* qsort(arr, sz, sizeof(arr[0]), cmp_Stu_age);*/
qsort(arr, sz, sizeof(arr[0]), cmp_Stu_name);
}
int main()
{
test();
return 0;
}
字符串之间不能相减进行比较,用strcmp函数,比较规则是基于字典(z>l)
比如abcdef 和 abq q>c 所以abq大
*void e1 不能解引用,可以强制类型转化进行解引用
8.指针数组题
9.做题图片帮助理解