首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C语言新手村】小怪升级 指针plus版

【C语言新手村】小怪升级 指针plus版

作者头像
f狐o狸x
发布2024-11-19 17:28:51
发布2024-11-19 17:28:51
1220
举报

本篇文章,我们将一起探讨指针高级版

一、指针数组、数组指针

1.1 指针数组

就是存放指针的数组,因此指针数组是一个数组,不是指针

例如:

int* pa[5]; //整型指针的数组 char* pb[2]; //字符型指针的数组 int** pc[3]; //二级整型指针的数组

1.2 数组指针

意为指向数组的指针

例如:

int(*pa)[5]; //指向整型数组的指针 char(*pb)[3]; //指向字符型数组的指针

这里其实就是pa先和“ * ”结合,因为“ [ ] ”他的优先级高于“ * ”

那么下面这个是数组还是指针?

int* (*pa)[3];

一步一步来看,( *pa )是一个指针,这个指针指向一个数组( * pa ) [ 3 ],这个数组的类型为int*

所以他是一个指向 int* 型数组的指针

1.3 数组名和&数组名

上面讲述了指向数组的指针,那么他接收的是什么呢?

例如:

以下打码打印出的结果是什么?

代码语言:javascript
复制
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	return 0;
}

这里可以看出arr和&arr打印的地址都是一样的,那么他两的意思是一样的吗?

代码语言:javascript
复制
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("%p\n", arr + 1);
	printf("%p\n", &arr + 1);
	return 0;
}

我们打印+1以后的结果来看一下

这里他俩的结果就不一样了

原因是arr是数组的首元素的地址,而&arr是整个数组的地址,因此arr + 1跳过4个字节,而&arr + 1跳过的是5 * 4 = 20个字节

二、 函数指针

2.1 函数指针的定义

函数指针就是指向函数的指针

例如:

代码语言:javascript
复制
void test()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("%p\n", arr + 1);
	printf("%p\n", &arr + 1);
}

int main()
{
	void (*pf)() = test;
	(*pf)();
	return 0;
}

因此可以看出,函数指针的定义为:

void (*pfun1)( );

2.2 函数指针数组

就是一个存放了函数指针的数组

定义为:

void (*pf[5])( ) = { 0 };

2.3 函数指针数组的应用

合理运用函数指针数组可以帮我们简化很多代码,例如计算器的实现:

代码语言:javascript
复制
 void menu()
{
	 printf("********************************\n");
	 printf("*****   1.add      2.sub   *****\n");
	 printf("*****   3.mul      4.div   *****\n");
	 printf("*****   0.exit             *****\n");
	 printf("********************************\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;
 }

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请输入:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

上面这个计算器的代码是不是略显繁琐

这里我们就可以运用函数指针数组将上面的加减乘除的函数装起来

代码语言:javascript
复制
//函数指针数组
int(*pf[5])(int, int) = { NULL,add,sub, mul,div };
 
int main()
 {
	 int input = 0;
	 int x = 0;
	 int y = 0;
	 int ret = 0;
	 do
	 {
		 menu();
		 printf("请输入:");
		 scanf("%d", &input);
		 if (input >= 1 && input <= 4)
		 {
			 printf("请输入两个操作数:");
			 scanf("%d %d", &x, &y);
			 ret = (*pf[input])(x, y);
			 printf("%d\n", ret);
		 }
		 else if (input == 0)
		 {
			 printf("退出计算器\n");
			 break;
		 }
		 else
		 {
			 printf("输入错误\n");
		 }
	 } while (input);
	 return 0;
 }

这样代码就简化了很多

三、回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

例如上述计算器的函数还可以简化为:

代码语言:javascript
复制
void calc (int(*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}

int main()
{
	int input = 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;
}

这样的代码是不是更简化了

3.1 回调函数的应用

回调函数还有个典型的运用例子,qsort( )函数的调用,qsort可以对任何类型的变量进行排序。话不多说,直接上代码

代码语言:javascript
复制
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1) - (*(int*)e2);
}

int main()
{
	int arr[10] = { 5,2,4,3,6,8,9,7,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr,sz,sizeof(int),cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

也可以自己写一个练习一下

代码语言:javascript
复制
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1) - (*(int*)e2);
}

void swap(char* e1, char* e2, size_t width)
{
	size_t i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = tmp;
	}
}

void new_qsort(const void* base, size_t sz, size_t width, int(*pf)(const void*e1, const void*e2))
{
	
	size_t i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		size_t j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (pf((char*)base + j * width,(char*)base + (j + 1) * width) > 0)
			{
				//交换
				swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	new_qsort(arr,sz,sizeof(int),cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

本章内容就到这里, 下一期我们说说常见的指针题型

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、指针数组、数组指针
    • 1.1 指针数组
    • 1.2 数组指针
    • 1.3 数组名和&数组名
  • 二、 函数指针
    • 2.1 函数指针的定义
    • 2.2 函数指针数组
    • 2.3 函数指针数组的应用
  • 三、回调函数
    • 3.1 回调函数的应用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档