进阶C语言-指针的进阶(二)

这篇具有很好参考价值的文章主要介绍了进阶C语言-指针的进阶(二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构

📖5.函数指针

数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。
函数指针 - 指向函数的指针 - 存放的是函数的地址 - &函数名就是函数的地址。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	//&函数名就是函数的地址
	//函数名也是函数的地址
	printf("%p\n", &Add);
	printf("%p\n", Add);
	int (*pd1)(int, int) = &Add;
	//int (*pd2)(int, int) = Add;//pd2是函数指针变量
	int ret = (*pd1)(3, 5);
	printf("%d\n", ret);
	return 0;
}

进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构
🔭阅读下面这两段代码:

//代码1:
(*(void (*)())0)();
//void (*)()为函数指针类型
//下面这段代码是在调用0地址处的函数,这个函数没有参数,返回类型是void
//代码2:
void (*signal(int , void(*)(int)))(int);
//signal函数的参数有两个,第一个是int类型,第二个是函数指针类型,该类型是void(*)(int),该函数指向的类型是int,返回类型是void.signal函数也是函数指针类型,该类型是void(*)(int),该函数指向的类型是int,返回类型是void.

📖6.函数指针数组

🔭 指针数组:
字符指针数组 - 数组 - 存放的是字符指针
整型指针数组 - 数组 - 存放的是整型指针
那么函数指针数组 - 数组 - 存放的是函数指针 - 存放的是函数的地址。

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int main()
{
	int (*pf1)(int, int) = &Add;
	int (*pf2)(int, int) = &Sub;
	int (*pfArr[4])(int, int) = { &Add,&Sub };
	//pfArr是函数指针数组,是存放函数指针的数组 
	return 0;
}

🔎这里我们来模拟一下计算器的实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
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("请输入2个操作数:");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("请输入2个操作数:");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("请输入2个操作数:");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("请输入2个操作数:");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序!\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}

✅自测运行:
进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构
🎈程序不足:如果想要实现更多的功能||、&&、&、|、>>、<<等等,还得重复写一些步骤,就很冗余!
🏆这里,我们就可以利用函数指针数组的知识来优化它,函数指针数组的作用:转移表!

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
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);
		//函数指针数组-转移表
		int (*pfarr[])(int, int) = { NULL,Add,Sub,Mul,Div };
		if (0 == input)
		{
			printf("退出程序!\n");
		}
		else if (input >= 1 && input <= 4)
		{
			printf("请输入2个操作数:");
			scanf("%d%d", &x, &y);
			ret = pfarr[input](x, y);
			printf("ret = %d\n", ret);
		}
		else
		{
			printf("选择错误,请重新选择!\n");
		}
	} while (input);
	return 0;
}

进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构

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

指向函数指针数组的指针是一个指针,指针指向一个数组,数组的元素都是函数指针。

如何定义?

void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[5])(const char*) = &pfunArr;
return 0;
}

📖8.回调函数

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

🔎这里,我们利用回调函数实现一下计算器:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
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;
}
void calc(int (*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入2个操作数:");
	scanf("%d%d", &x, &y);
	ret = pf(x, y);
	printf("ret = %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;
}

✅自测运行:
进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构
🔎这里,我们演示一个qsort函数的实现:

qsort函数是一个库函数,底层使用的是快速排序的方式,对数据进行排序的这个函数可以直接使用,这个函数可以用来排序任意类型的数据。

🌞我们先一起回顾一下冒泡排序的内容:

//冒泡排序算法:
//给一组整型数据,然后使用冒泡排序算法,对数据进行升序排列
//冒泡排序的思想:两两相邻的元素进行比较
#include <stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
void print_arr(int *arr,int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);//排序前
	bubble_sort(arr, sz);
	print_arr(arr, sz);//排序后
	return 0;
}

进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构

🎈缺陷:我们发现这个函数不够通用,只能排序整型类型!
📝关于qsort函数,我们可以先去cpluplus网站上面了解一下:

进阶C语言-指针的进阶(二),进阶C语言,c语言,算法,数据结构

//1.排序整型数组,两个整型可以直接使用大于号比较。
//2.排序结构体数组,两个结构体数据可能不能直接使用大于号比较。
//不同类型的数据,比较出大小,方法是有差异的。
void qsort (void* base//待排序数组的第一个元素的地址
,           size_t num//待排序数组的元素个数
,           size_t size//待排序数组中一个元素的大小
,           int (*compar)(const void* e1,const void* e2));//函数指针compar指向了一个函数,这个函数是用来比较两个元素的
//e1和e2中存放的是需要比较的两个元素的地址

🔭关于void*类型的指针:

  1. void*类型的指针 - 不能进行解引用操作符,也不能进行±整数的操作
  2. void*类型的指针是用来存放任意类型数据的地址
  3. void*无具体类型的指针
#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < count - 1; i++)
	{
		for (j = 0; j < count - i - 1; j++)
		{
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}
int main()
{
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	//char *arr[] = {"aaaa","dddd","cccc","bbbb"};
	int i = 0;
	bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

好啦,关于进阶指针(中)的知识点到这里就结束啦,后期会继续更新C语言的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️文章来源地址https://www.toymoban.com/news/detail-725986.html

到了这里,关于进阶C语言-指针的进阶(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手撕数据结构与算法——树(三指针描述一棵树)

    📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段, 因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力 ——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:king南星 📖

    2024年01月17日
    浏览(39)
  • C语言进阶——数据结构之链表(续)

    hello,大家好呀,我是Humble,本篇博客承接之前的 C语言进阶——数据结构之链表 的内容 (没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~) ,上次我们重点说了链表中的 单链表 ,即 不带头单向不循环链表 还说到了链表的分类虽

    2024年01月25日
    浏览(50)
  • 【C语言进阶篇】看完这篇结构体文章,我向数据结构又进了一大步!(结构体进阶详解)

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,结构体的基本使用和常见错误在上一篇详细讲解过了,不知道大家都学会了没有。    ⛳️ 今天给大家来个硬菜,教点高

    2024年02月15日
    浏览(35)
  • 【算法数据结构系列】哈夫曼树进阶解读

    作者:半身风雪 简介:移动开发全栈领域工作者

    2024年02月10日
    浏览(32)
  • C语言完整版笔记(初阶,进阶,深刨,初阶数据结构)

    1.初阶: 1.1C语言初阶易忘知识点速记 2.进阶:  1.2C语言进阶易忘点速记 3.深剖: 2.1C语言重点解剖要点速记 2.2C语言重点解剖操作符要点速记   2.3C语言重点解剖预处理要点速记 2.4C语言重点解剖指针和数组要点速记 2.5C语言重点解剖内存管理函数要点速记 4.数据结构:

    2024年02月16日
    浏览(27)
  • 【数据结构与算法】- (带尾指针)单循环链表 - 详细实现步骤及代码(C/C++)

    前三篇文章分别介绍了 “带头结点单链表实现”、“不带头结点单链表实现”、“带头结点单循环链表实现”。 这篇文章主要介绍 带尾指针 的单循环链表以及详细的实现步骤,最后提供我自己根据理解实现带尾指针单循环链表的C语言代码 。跟着后面实现思路看下去,应该

    2024年02月16日
    浏览(31)
  • 数据结构——排序算法(C语言)

    本篇将详细讲一下以下排序算法: 直接插入排序 希尔排序 选择排序 快速排序 归并排序 计数排序 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某写的大小,按照递增或递减0排列起来的操作。 稳定性的概念 假定在待排序的记录序列中,存在多个

    2024年02月08日
    浏览(42)
  • C语言数据结构与算法

    冒泡排序 例题 顺序表下的 冒泡排序 注意:冒泡排序 稳定,最多执行n(n-1)/2次 选择排序不稳定,平均比较次数n(n-1)/2 直接插入排序,是在有序基础上,速度最快且稳定的排序方法。 希尔排序是 不稳定的 顺序查找 二分查找(非递归) 二分查找(递归) 数组 链表 查询 快 慢

    2024年02月06日
    浏览(54)
  • 数据结构和算法——用C语言实现所有图状结构及相关算法

    本文所有代码均在仓库中,这是一个完整的由纯C语言实现的可以存储任意类型元素的数据结构的工程项目。 首先是极好的工程意识,该项目是一个中大型的CMake项目,结构目录清晰,通过这个项目可以遇见许多工程问题并且可以培养自己的工程意识。 其次是优秀的封装性(

    2024年02月06日
    浏览(43)
  • 数据结构与算法——排序(C语言实现)

    ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ 🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿 🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟 🌟🌟 追风赶月莫停留 🌟🌟 🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀 🌟🌟 平芜尽处是春山

    2024年04月09日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包