首页 > 其他分享 >C语言指针plus版

C语言指针plus版

时间:2024-09-28 17:22:44浏览次数:9  
标签:arr int void C语言 plus 数组 printf 指针

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

一、指针数组、数组指针

        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 数组名和&数组名

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

        例如:

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

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	return 0;
}

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

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 函数指针的定义

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

        例如:

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 函数指针数组的应用

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

 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;
}

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

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


//函数指针数组
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;
 }

        这样代码就简化了很多

三、回调函数

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

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

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可以对任何类型的变量进行排序。话不多说,直接上代码

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;
}

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

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;
}

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

标签:arr,int,void,C语言,plus,数组,printf,指针
From: https://blog.csdn.net/m0_74779094/article/details/142612039

相关文章

  • SpringBoot与MyBatis-Plus的整合与综合实例
    MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程、以及高级映射。MyBatis3提供的注解可以取代XML。例如,使用注解@Select直接编写SQL完成数据查询。MyBatis-Plus是一个对MyBatis进行增强的工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生......
  • MyBatis-Plus分页查询
    在实际开发中,对于大量数据的查询,可以通过分页查询的方式来减少查询量和提高查询效率。在MyBatis-Plus中,分页查询可以通过使用Page对象和IService接口提供的分页方法来实现。MyBatis-Plus的分页插件PaginationInnerInterceptor提供了强大的分页功能,支持多种数据库,使得......
  • C语言语句
    C语言语句C语言中的的代码是由一条条语句构成,而基本语句分为:•空语句•表达式语句•函数调⽤语句•复合语句•控制语句空语句简而言之,无语句,一个分号为一条语句#include<stdio.h>//主函数intmain(){ ;//空语句 return0;}表达式语句表达式语句......
  • 初始C语言
    C语言程序设计初始C语言初始C语言主要讲解其基础语法、常量变、运算符等等,这是C语言最基本得语法结构,这些是支撑一个程序的必需品,是重中之重。基础语法C语言的令牌主要包括以下几种类型:关键字(Keywords)标识符(Identifiers)常量(Constants)字符串字面量(StringLiterals)......
  • 深入剖析 MyBatis-Plus:操作总结、对比与实践案例(CRUD 操作、分页、条件构造器、自动填
    MyBatis-Plus是MyBatis的增强工具,它极大简化了MyBatis的配置和操作,提高了开发效率。本文从基本操作到高阶用法,详细介绍了MyBatis-Plus的常见功能及与MyBatis的区别,并通过实际案例展示其强大的扩展能力。MyBatis-Plus基于MyBatis,但旨在减少开发者的代码量,增强可......
  • Tauri2.0+Vite5聊天室|vue3+tauri2+element-plus仿微信|tauri聊天应用
    原创tauri2.0+vue3+pinai2仿QQ/微信客户端聊天Exe程序TauriWinChat。tauri2-vue3-winchat自研vite5+tauri2.0+vue3setup+element-plus跨平台仿QQ|微信桌面端聊天软件。全新封装tauri2多开窗口管理、自定义圆角阴影窗体。实现聊天、通讯录、收藏、我的、朋友圈/小视频等模块。......
  • 实验1 c语言输入输出和简单程序编写
    任务1:task1.11#include<stdio.h>2345intmain()6{7printf("o\n");8printf("<H>\n");9printf("II\n");10printf("o\n"......
  • 【C语言用筛选法求质数】
    C语言用筛选法求质数筛选法,另一种思路的求质数方法上面的方法数越大判断次数越多,运算时间越长,效率越差,如果对于给定的一个集合,可以用筛选法,思路是将集合中的非质数(合数)标出来,余下来的就是质数了。给定的字符数组charprime[100]={0};,初始化为0,默认全是质数:-)!prime[0]=......
  • 【C语言标准库函数】标准输入输出函数详解2:字符串输入输出
    目录一、字符串输入函数1.1.gets函数(已废弃)1.1.1.函数简介1.1.2.注意和废弃原因1.2.fgets函数1.2.1.函数简介1.2.2.使用场景1.2.3.注意事项1.2.4.示例二、字符串输出函数2.1.puts函数2.1.1.函数简介2.1.2. 使用场景2.1.3.注意事项2.1.4.示例2.2.......
  • C语言 16 系统库
    前面了解了如何使用#include引入其他文件,接着来了解一下系统提供的一些常用库。字符串计算字符串长度:#include<stdio.h>#include<string.h>intmain(){char*c="HelloWorld!";//使用strlen计算长度,注意返回值类型是size_t(别名而已,本质上就是unsignedlong)......