当前位置: 首页 > news >正文

10.2 指针进阶_函数指针

指针进阶

  • 5. 函数指针
  • 6. 函数指针数组
  • 7. 指向函数指针数组的指针
  • 8. 回调函数

10.1 指针进阶_数组指针
10.3 指针进阶_代码分析

5. 函数指针

void test()
{
	printf("hehe\n");
}
int main()
{
	printf("%p\n", test);
	printf("%p\n", &test);
	return 0;
}
006013B6
006013B6
test和&test都是函数地址

eg

void test(char* pc, int arr[10])
{ }
int main()
{
	void (*pf)(char*, int arr[]) = test;
	return 0;
}

eg

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int arr[10] = { 0 };
	int(*pa)[10] = &arr;//类比
	int(*pf)(int, int) = &Add;
	//pf是函数指针变量
	return 0;
}

使用指针调用函数

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int(*pf)(int, int) = &Add;
	int r = Add(3, 5);
	printf("%d\n", r);
	int m = (*pf)(4, 5);
	//--> int m = pf(4, 5);
	//pf和Add一回事
	printf("%d\n", m);
	return 0;
}

eg1.代码分析

(*(void (*)())0)();

void (*p)()-->p是函数指针
void (*)() -->函数指针类型
(void (*)())0-->强制类型转换, 0转换成 void (*)()0的地址中存放着这个函数
*(void (*)())0-->解引用,调用这个函数
(*(void (*)())0)()-->调用时无参数
(*(void (*)())0)();-->调用0地址处的函数

eg2.代码分析

void (*signal(int , void(*)(int)))(int);

void (*p)(int); -->函数指针
void(*)(int)-->函数指针指向一个int类型的参数,返回类型void
signal(int , void(*)(int))--> signal 函数(类型 int ,函数指针类型 void(*)(int))

简化

//typedef重定义
typedef unsigned int uint;
typedef int* ptr_t;

typedef int(*parr_t)[10];
typedef int(*pf_t)(int,int);

int main()
{
	uint u1;
	ptr_t p1;
	int* p2;
	return 0;
}
void (*signal(int , void(*)(int)))(int);
--->
	typedef void(*pf_yt)(int);
	//void (*signal(int, void(*)(int)))(int);
	pf_yt signal(int, pf_yt);

6. 函数指针数组

int Add(int x, int y) {
	return x + y;
}
int Sub(int x, int y) {
	return x - y;
}
int Mul (int x, int y) {
	return x * y;
}
int Div(int x, int y) {
	return x / y;
}
int main() {
	//int(*pf1)(int, int) = Add;
	//int(*pf2)(int, int) = Sub;
	//int(*pf3)(int, int) = Mul;
	//int(*pf4)(int, int) = Div;
	//函数指针数组
	int (*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("1.Add 2.Sub 3.Mul 4.Div\n");
	scanf("%d", &input);
	printf("输入两个操作数\n");
	scanf("%d %d", &x, &y);
	ret = pfArr[input](x, y);
	printf("ret = %d\n", ret);
	return 0;
}

7. 指向函数指针数组的指针

int (*pf)(int, int);//函数指针
int (*pfArr[4])(int, int);//函数指针数组pfArr
int (*(*p)[4])(int, int) = &pfArr;//函数指针  数组的地址
//p就是指向函数指针数组的指针

8. 回调函数

回调函数:通过函数指针调用的函数。
把函数的指针(地址)作为参数传递给另一个函数,指针被用来调用其所指向的函数。
回调函数不是由该函数的实现方直接调用,而是由另外的一方调用的。

void menu() {
	printf("* 1.add  2.sub *\n");
	printf("* 3.mul  4.div *\n");
	printf("* 0.exit       *\n");
}
int Add(int x, int y) {
	return x + y;
}
int Sub(int x, int y) {
	return x - y;
}
int Mul (int x, int y) {
	return x * y;
}
int Div(int x, int y) {
	return x / y;
}
void Calc(int(*pf)(int, int)) {
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("输入两个操作数\n");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}
int main() {
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do {
		menu();
		printf("请输入> ");
		scanf("%d", &input);
		switch (input) {
		case 1:
			Calc(Add);//回调函数
			break;
		case 2:
			Calc(Sub);
			break;
		case 3:
			Calc(Mul);
			break;
		case 4:
			Calc(Div);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

标准库中qsort函数用来排序
qsort

  1. 快速排序
  2. 适合任意类型
void qsort( void* base,//指向需要排序数组的第一个元素
			size_t num,//排序的元素个数
			size_t width,//一个元素的大小,单位是字节
			int(__cdecl* compare)(const void* elem1, const void* elem2)//函数指针类型
			);
viod* -->无具体类型指针,可以接收任意类型的地址。
不能直接解引用,不能直接进行指针运算。
因为不知道类型,不知道访问多少字节空间。
#include <stdlib.h>
//qsort排序整形
int cmp_int(const void* p1, const void* p2) {
	return(*(int*)p1 - *(int*)p2);
}
void print(int arr[], int sz){
	int i = 0;
	for (i -= 0; i < sz; i++) {
		printf("%d ", arr[i]);
	}
}
test1() {
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//qsort默认是升序
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);
}
int main() {
	test1();
	return 0;
}

0 1 2 3 4 5 6 7 8 9

//qsort排序结构体数据_age
struct Stu {
	char name[20];
	int age;
};
int cmp_stu_by_age(const void* p1, const void* p2) {
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
void test2() {
	struct Stu arr[] = { {"alice",30},{"bob",20},{"ruarua",10} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
int main() {
	//test1();
	test2();
	return 0;
}
名称类型
arr0x009af81c {{name=0x006ff7ac “alice” age=30 }, {name=0x006ff7c4 “bob” age=20 }, {name=0x006ff7dc “ruarua” …}}Stu[3]
[0]{name=0x006ff7ac"alice" age=30 }Stu
[1]{name=0x006ff7c4 “bob” age=20 }Stu
[2]{name=0x006ff7dc “ruarua” age=10 }Stu
–>
名称类型
arr0x006ff7ac {{name=0x006ff7ac “ruarua” age=10 }, {name=0x006ff7c4 “bob” age=20 }, {name=0x006ff7dc “alice” …}}Stu[3]
[0]{name=0x006ff7ac “ruarua” age=10 }Stu
[1]{name=0x006ff7c4 “bob” age=20 }Stu
[2]{name=0x006ff7dc “alice” age=30 }Stu
//qsort排序结构体数据_name
struct Stu {
	char name[20];
	int age;
};
int cmp_stu_by_name(const void* p1, const void* p2) {
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
void test3() {
	struct Stu arr[] = { {"zalice",30},{"tbob",20},{"aruarua",10} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main() {
	//test1();
	//test2();
	test3();
	return 0;
}
名称类型
arr0x0054f6b4 {{name=0x0054f6b4 “zalice” age=30 }, {name=0x0054f6cc “tbob” age=20 }, {name=0x0054f6e4 “aruarua” …}}Stu[3]
[0]{name=0x0054f6b4 “zalice” age=30 }Stu
[1]{name=0x0054f6cc “tbob” age=20 }Stu
[2]{name=0x0054f6e4 “aruarua” age=10 }Stu

–>

名称类型
arr0x0054f6b4 {{name=0x0054f6b4 “aruarua” age=10 }, {name=0x0054f6cc “tbob” age=20 }, {name=0x0054f6e4 “zalice” …}}Stu[3]
[0]{name=0x0054f6b4 “aruarua” age=10 }Stu
[1]{name=0x0054f6cc “tbob” age=20 }Stu
[2]{name=0x0054f6e4 “zalice” age=30 }Stu

10.1 指针进阶_数组指针
10.3 指针进阶_代码分析

相关文章:

  • 2025年上海安卓发展机遇
  • 云计算:重塑数字世界的基石
  • spring的15个经典面试题
  • 深入解析Spring核心扩展点:BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor
  • (十 二)趣学设计模式 之 享元模式!
  • Unity小功能实现:鼠标点击移动物体
  • 5G学习笔记之BWP
  • 用DeepSeeker + AI app工具自动生成 APP代码
  • 【深度学习】输入长度大于训练时输入长度会发生什么?LSTM 和 Transformer对比。
  • 深入浅出 Go 语言:协程(Goroutine)详解
  • Flutter - 布局Widget
  • Java的流表达式使用
  • ClickHouse深度解析:OLAP领域的性能怪兽
  • 爬虫系列之【数据解析之JSON】《三》
  • leetcode日记(74)合并两个有序数组
  • 蓝耘元生代智算云:解锁百亿级产业变革的算力密码
  • 【STM32安全性研究】STM32F103RCT6固件读取
  • 计算机毕业设计SpringBoot+Vue.js常规应急物资管理系统(源码+文档+PPT+讲解)
  • c++中explicit的作用
  • UI组件库及antd
  • 海外市场,押注中国无人驾驶龙头
  • 新疆多地市民拍到不明飞行物:几秒内加速消失,气象部门回应
  • 2025年上海科技节开幕,人形机器人首次登上科学红毯
  • 视频丨歼-10CE首次实战大放异彩
  • 女排奥运冠军宋妮娜:青少年保持身心健康才能走得更远
  • 马上评|家长抱婴儿值护学岗,如何避免“被自愿”?