第十一讲:指针(3)

第十一讲:指针(3)

  • 1.字符指针变量
    • 1.1存储一个字符
    • 1.2存储一个字符串
    • 1.3一个有趣的面试题
  • 2.数组指针变量
    • 2.1什么是数组指针变量
    • 2.2数组指针变量的初始化
  • 3.二维数组传参的本质
  • 4.函数指针变量
    • 4.1介绍函数指针变量
    • 4.2 两段有趣的代码
      • 4.2.1代码1
      • 4.2.2代码2
    • 4.3typedef关键字
  • 5.函数指针数组
  • 6.转移表
    • 6.1一般写法
    • 6.2函数指针数组写法

1.字符指针变量

1.1存储一个字符

我们当然可以使用指针来存放一个字符变量,使用方法如下:
在这里插入图片描述

1.2存储一个字符串

那么如果我们用指针存放字符串会发生什么呢?

结论:
1.指针存放字符串时存放的时一个字符串首元素的地址
2.直接使用指针存放字符串时,这个字符串被称为常量字符串,此时字符串的值不能被改变


int main()
{
	char* pa = "abcdef";   //此时abcdef就是一个常量字符串
	                       //pa中存储的是首元素a的地址,证明如下:
	printf("%c\n", *pa);  //此时打印出的是a

	//*pa = 'c';  如果想要改变pa的值,程序会崩溃,但是并不会报错

	//所以我们不如将上面的代码表示如下
	const char* pb = "abcd";
	//*pb = 0;   此时如果再想改变pb的值,程序就会报错
	return 0;
}

1.3一个有趣的面试题

在这里插入图片描述
这个面试题的结果为:
在这里插入图片描述
原因如下:
str3和str4指向的是同一个常量字符串,常量字符串会存储再内存中的常量区,它的地址是确定的,而使用str1和str2初始化数组时,就会开辟不同的内存块

2.数组指针变量

2.1什么是数组指针变量

类比于
整形指针变量(int * pa),存放的时整形变量的地址,能够指向整形数据
浮点型指针变量(float * pb),存放的是浮点型变量的地址,指向浮点型数据
那么数组指针变量应该是:
存放的是数组的地址,能够指向数组的指针变量

指针变量的表示方法如下:
在这里插入图片描述
pa先和*进行结合,说明pa是一个指针变量,指向的是一个大小为5的数组。所以pa是一个指针,指向一个数组,称为数组指针

2.2数组指针变量的初始化

在这里插入图片描述
如果要存放个数组的地址,就得存放在数组指针变量中
数组指针解析:
在这里插入图片描述

3.二维数组传参的本质

结论:
二维数组传参,传入的是二维数组中首个一维数组的地址

我们用代码和图像来进一步理解二维数组传参的本质:


//二维数组传参的本质 (打印二维数组的每一个元素)
Print(int(*pa) [3], int r, int c)  //二维数组传参的本质是传入了首个一维数组的地址,而首个一维数组的类型是int [3],
{                                   //所以接受的指针类型是int (*)[3]的类型
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			printf("%d ", (*(pa + i))[j]); //这里的(*(pa + i))[j]相当于*(*(pa+i)+j)相当于pa[i][j]
		}
		printf("\n");
	}
}

int main()
{
	int arr[2][3] = { {1,2,3}, {2,3,4} };
	Print(arr, 2, 3);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
当然,二维数组进行传参时,也可以用二维数组来接受:

Print(int arr[2][3], int r, int c)

4.函数指针变量

4.1介绍函数指针变量

类比于数组指针变量(用来存放数组的地址),函数指针变量是用来存放函数的地址的,对于函数的地址的理解:
在这里插入图片描述
我们可以看出来,函数名其实就是函数的地址,Add == &Add,为了将函数的地址存下来,就要使用函数指针变量,使用方法如下:


//函数指针的使用
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 2;
	int b = 3;
	         //(int x, int y)中x和y写不写都可以
	int (*Pa)(int, int) = Add; //将Add函数的地址存储在函数指针变量中,Add和&Add等价
	printf("%d\n", Pa(a, b));  //在使用时,pa(a,b)和(*pa)(a,b)等价
	return 0;
}

函数指针类型解析:
在这里插入图片描述

4.2 两段有趣的代码

4.2.1代码1

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

对于上述代码的解释如下:
在这里插入图片描述

4.2.2代码2

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

在这里插入图片描述

4.3typedef关键字

typedef是用来类型重命名的,可以将复杂的类型简单化,具体使用方法如下:


//typedef关键字
typedef unsigned int uint;    //1.使用关键字定义普通类型的名称
typedef int* pa;              //2.使用关键字定义指针类型的名称
typedef int(*ppa)[4];         //3.使用关键字定义数组指针的名称
typedef int(*pppa)(int, int); //4.使用关键字定义函数指针变量名称

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	uint a = 3;  //关键字的使用
	printf("%d\n", a);

	pa p_a = &a;
	*p_a = 4;
	printf("%d\n", a);
	
	int arr[4] = { 1,2,3,4 };
	ppa p_arr = &arr;
	for (int i = 0; i < 4; i++)
	{
		printf("%d ", *((*p_arr) + i));
	}
	printf("\n");

	pppa p_add = Add;
	int ret = p_add(2, 3);
	printf("%d", ret);
	return 0;
}

那么此时我们就可以简化代码2,将其转换成:

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

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

5.函数指针数组

函数指针数组是存放函数指针的数组,那么函数指针数组如何使用呢?


//函数指针数组的使用
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int (*pa[3])(int, int) = { Add };
	int ret = pa[0](2, 3);
	printf("%d", ret);
	return 0;
}

6.转移表

函数指针的用途:转移表
举例:计算器的一般实现

6.1一般写法


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;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("输⼊操作数:");
			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;
}

显然,这个方法比较啰嗦,不好用

6.2函数指针数组写法


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;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int (*pa[5])(int, int) = { 0, add, sub, mul, div };
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if (input >= 1 && input <= 5)
		{
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			int ret = pa[input](x, y);
			printf("%d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出程序!");
			break;
		}
		else
			printf("输入的值非法,重新输入:");
		
	} while (input);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/611098.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为 Huawei 交换机 配置 Dot1q 终结子接口实现同设备 VLAN 间通信示例

组网需求 企业的不同部门拥有相同的业务&#xff0c;如上网、 VoIP 等业务&#xff0c;且各个部门中的用户位于不同的网段。目前存在不同的部门中相同的业务所属的VLAN 不相同&#xff0c;现需要实现不同VLAN中的用户相互通信。 如 图 7-7 所示&#xff0c;部门 1 和部门 2 中…

机器学习的一些知识点分享

下面数据集中&#xff0c;第2个样本的第4个属性的值是&#xff08; &#xff09;。 A 52 B 男 C 50 D 49 本题得分&#xff1a; 2分 正确答案&#xff1a; D 2.单选题 (2分) 10-折交叉验证是把数据集分成&#xff08; &#xff09;个子集&#xff0c;将其中&#xff…

好景盒式磁带随声听

少年时代柜子里翻出来的磁带录音机电路板 两颗芯片&#xff0c;FM芯片&#xff0c;电机驱动 CD9088CBD6650

第十三届蓝桥杯决赛(国赛)真题 Java C 组【原卷】

文章目录 发现宝藏试题 A: 斐波那契与 7试题 B: 小蓝做实验试题 C: 取模试题 D: 内存空间试题 E \mathrm{E} E : 斐波那契数组试题 F: 最大公约数试题 G: 交通信号试题 I: 打折试题 J: 宝石收集 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#x…

VM虚假机联网(无代码,超简单)NAT模式

1、左边顶上编辑里面最下面找到虚拟网络编辑器2.启用管理员特权3.重新创建一个NAT模式的网络&#xff08;名称随便一个&#xff09; 4.打开这两个设置里面的东西进行拍照并记住IP区间和网关&#xff0c;等下要用&#xff1b; 5.打开虚拟机&#xff0c;右上角&#xff0c;下标点…

sql注入中的替换技巧。

目录 1&#xff1a;注释的替换 2&#xff1a;空格替换 3&#xff1a;大小写混合绕过及双写绕过 4&#xff1a;等号的绕过 5&#xff1a;单双引号的绕过 1&#xff1a;注释的替换 注释在sql注入中非常重要&#xff0c;因为会使用它来闭合我们注入的sql语句。 当以get方式提…

idea运行项目报错提示:java: 错误: 不支持发行版本 19,让我来看看

在项目经常切换jdk时&#xff0c;这个error经常能遇到“不支持发行版本19”&#xff0c;这个问题修改起来其实很简单&#xff0c;但在真正操作到能够解决问题的那一步前&#xff0c;通常习惯先去查看配置的jdk版本是否是选择正确的&#xff0c;也就是先确认当前这个项目选择的j…

【全部更新】2024数维杯B题详细成品文章代码思路结果分享

生物质和煤共热解问题的研究 摘要 这个问题背景主要涉及生物质和煤共热解的研究。在共热解过程中&#xff0c;生物质和煤一起在高温和缺氧条件下热解&#xff0c;产生气体、液体和固体产物。研究生物质和煤共热解油的产率和品质机理对提高能源利用效率、促进资源综合利用和确保…

该问题未得到解决(仅记录)

https://releases.ubuntu.com/bionic/进入网页下载ubuntu 选择烧录软件将下载的Ubuntu烧录到U盘中 之前用这个U盘烧录过一次&#xff0c;成功了&#xff0c;后来应该是U盘受损或者是什么其他原因使得用这个U盘总是烧录失败

关于Ardupilot的固定翼(plane)的控制

起因 由于项目原来是使用的四旋翼,并且是PX4版本的四旋翼; 如今需要对无人机固定翼进行控制,并要求使用Ardupilot的固件进行研究。 特定在此记录对固定翼的学习,以和大家分享观点和交流学习。 PX4和Ardupilot关系 PX4和Ardupilot都是固件,固件就是软件的意思。两者都是…

重载,重写,重定义,纯虚函数,多态习题

只要不够成重写就是重定义。 重定义&#xff1a; 抽象类&#xff1a; 包含纯虚函数的类就是抽象类。 1.纯虚函数的作用&#xff0c;强制子类去完成重写。 2.表示抽象的类型。 抽象就是在现实中没有对应的实体。 1. 下面哪种面向对象的方法可以让你变得富有( a) A 继承 B…

四、用nodejs写新增接口

&#xff08;1&#xff09;新增数据库 选择不区分大小写 在新建查询内编译 &#xff08;2&#xff09;新建提交代码的表 create TABLE code_record( id INT not null auto_increment, name VARCHAR(200) not null, course VARCHAR(200) not null, mail VARCHAR(200) not null…

Spring框架学习笔记(二):Spring IOC容器配置 Bean,分别基于XML配置bean 和 基于注解配置 bean

1 Spring 配置/管理 bean 介绍 Bean 管理包括两方面 &#xff1a;创建 bean 对象&#xff1b;给 bean 注入属性 Bean 配置方式&#xff1a;基于 xml 文件配置方式&#xff1b;基于注解方式 2 基于 XML 配置 bean 2.1 通过类型来获取 bean 方法&#xff1a;给getBean传入一…

传输层之 TCP 协议

TCP协议段格式 源/目的端口号&#xff1a;表示数据是从哪个进程来&#xff0c;到哪个进程去。 序号&#xff1a;发送数据的序号。 确认序号&#xff1a;应答报文的序号&#xff0c;用来回复发送方的。 4 位首部长度&#xff1a;一个 TCP 报头&#xff0c;长度是可变的&#xff…

STM32学习和实践笔记(25):USART(通用同步、异步收发器)

一&#xff0c;STM32的USART简介 USART即通用同步、异步收发器&#xff0c;它能够灵活地与外部设备进行全双工数据交换&#xff0c;满足外部设备对工业标准 NRZ 异步串行数据格式的要求。 UART即通用异步收发器&#xff0c;它是在USART基础上裁剪掉了同步通信功能。 开发板上…

【Web】CTFSHOW 七夕杯 题解

目录 web签到 easy_calc easy_cmd web签到 CTF中字符长度限制下的命令执行 rce(7字符5字符4字符)汇总_ctf中字符长度限制下的命令执行 5个字符-CSDN博客7长度限制直接梭了 也可以打临时文件RCE import requestsurl "http://4ae13f1e-8e42-4afa-a6a6-1076acd08211.c…

Vision Mamba:高效视觉表示学习双向状态空间模型,超越Vision Transformer!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 引言&#xff1a;探索视觉领域的新方向 在计算机视觉领域&…

翻工第二次 Ant Design Pro 下载,发现问题,电脑网络配置有误,魔法了

一、相关网址链接 鱼皮的用户中心项目 &#xff08;前端Ant Design Pro构建&#xff09; 语雀 ## 没有选择umi版本这一步 Issue #11144 ant-design/ant-design-pro GitHub 关于umi ui图标未显示问题_umi ui不出现-CSDN博客 二、存在问题 导致下载速度慢 本人镜像代码写…

双向链表(详解)

在单链表专题中我们提到链表的分类&#xff0c;其中提到了带头双向循环链表&#xff0c;今天小编将详细讲下双向链表。 话不多说&#xff0c;直接上货。 1.双向链表的结构 带头双向循环链表 注意 这几的“带头”跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在…

第十三届蓝桥杯决赛(国赛)真题 Java A 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 火柴棒数字试题 B: 小蓝与钥匙试题 C: 内存空间试题 D: 斐波那契数组试题 E: 交通信号试题 F: 数组个数试题 G: 六六大顺试题 H : \mathrm{H}: H: 选素数试题 I: 图书借阅试题 J \mathrm{J} J : 括号序列树 发现宝藏 前些天发现了一个…
最新文章