第十一讲:指针(3)

news2024/11/18 12:39:28

第十一讲:指针(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.coloradmin.cn/o/1664231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Unity】Unity项目转抖音小游戏(二)云数据库和云函数

业务需求&#xff0c;开始接触一下抖音小游戏相关的内容&#xff0c;开发过程中记录一下流程。 抖音云官方文档&#xff1a;https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/cloud-function-debug 1.开通抖音云环境 抖音云地址&a…

【Spring源码分析】ResolvableType

【Spring源码分析】ResolvableType 参考 目录 文章目录 【Spring源码分析】ResolvableType一、ParameterizedType 参数化类型&#xff0c;即泛型&#xff1b;例如&#xff1a;List< T>、Map< K,V>等带有参数化的对象;二、GenericArrayType—— 泛型数组 泛型数组…

SOCKET编程(4):SOCKET实战

SOCKET实战 Writen()、Readn()函数 send()函数存在需要发送的字符数len小于函数返回的已发送的字符数(ssize_t)的问题 recv()函数存在需要接收的字符数len小于函数返回的已接收的字符数(ssize_t)的问题 解决上述问题通过Writen()、Readn()函数实现 //buff是数据存储地址&a…

矩阵的压缩存储介绍

引入 概述 特殊矩阵的压缩 对称矩阵 三角矩阵 上三角矩阵&#xff1a;上三角区的元素不同&#xff0c;下三角区的元素相同。 存储不同元素的上三角区(计算前i-1行的所有元素之和(j-i1)[i行的列数]-1[下标由0开始],即以下标为0开始存储的下标)一个相同元素(下三角区) 下三角矩…

Verlog-串口发送-FPGA

Verlog-串口发送-FPGA 引言&#xff1a; ​ 随着电子技术的不断进步&#xff0c;串口通信已成为嵌入式系统和计算机外设中一种广泛使用的异步通信方式。串口通信因其简单性、可靠性以及对硬件资源的低要求&#xff0c;在数据传输领域扮演着重要角色。在FPGA&#xff08;现场可编…

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环 1、 for i in range(4):Dev.step(i6)for j in range(3):Dev.turnLeft()Dev.step(2)2、 for i in range(4):Dev.step(i3)for j in range(4):Dev.step(2)Dev.turnRight()Dev.step(-i-3)Dev.turnRight()3、 for i …

ICode国际青少年编程竞赛- Python-4级训练场-嵌套for循环练习

ICode国际青少年编程竞赛- Python-4级训练场-嵌套for循环练习 1、 for i in range(3):Spaceship.step(4)for j in range(4):Dev.step(2)Dev.turnRight()Spaceship.turnLeft()Spaceship.step(4)Spaceship.turnRight()2、 for i in range(4):Spaceship.step(6)for j in range(3):…

SpringBoot实现图片验证码

引入依赖 <dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version> </dependency>代码实现 package com.qiangesoft.captcha.controller;import com.wf.captcha.*…

【LeetCode刷题记录】简单篇-108-将有序数组转换为二叉搜索树

【题目描述】 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 【测试用例】 示例1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,…

面向对象进阶——内部类

1、初始内部类 什么是内部类&#xff1f; 类的五大成员&#xff1a; 属性、方法、构造方法、代码块、内部类 在一个类的里面&#xff0c;再定义一个类。 举例&#xff1a;在A类大的内部定义B类&#xff0c;B类就被称为内部类 public class Outer{ 外部类 public …

计数问题C++

题目&#xff1a; 思路&#xff1a; 1~n之间进行循环遍历&#xff0c;如果i不等于0继续循环&#xff0c;然后求出i的个位数与十位数&#xff0c;如果个位数为要查找的特定数字&#xff0c;计时器就1. 代码&#xff1a; #include<iostream> using namespace std; int n,x…

80.网络游戏逆向分析与漏洞攻防-移动系统分析-利用数据包尝试穿墙

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

蛋糕店做配送小程序的作用是什么

蛋糕烘焙除了生日需要&#xff0c;对喜吃之人来说往往复购率较高&#xff0c;除线下实体店经营外&#xff0c;更多的商家选择线上多种方式获客转化、持续提高生意营收&#xff0c;而除了进驻第三方平台外&#xff0c;构建品牌私域自营店铺也同样重要。 运用【雨科】平台搭建蛋…

【软考高项】四十二、八大绩效域知识点

一、干系人绩效域 预期目标 建立高效的工作关系 检查&#xff1a;干系人参与的连续性 干系人认同项目目标 检查&#xff1a; 变更频率 支持项目的干系人提高了满意度&#xff0c;从中受益 检查&#xff1a;干系人行为、干系人满意度、干系人相…

Linux基础之进程

目录 一、进程的基本概念 1.1 什么是进程 1.2 PCB的概念 1.3 进程的查看 1.3.1 查看进程方式一 1.3.2 查看进程的方式二 1.4 父进程与子进程 一、进程的基本概念 1.1 什么是进程 进程是什么&#xff1f; 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的…

基于StatefulSet控制器在Kubernetes上部署MySQL一主多从

一、前提--StatefuSet特性 1.1 有状态的节点控制器 -- StatefulSet 及其网络状态 容器的解决方案是针对无状态应用场景的最佳实践&#xff0c;但对于有状态应用来说&#xff0c;就并非如此了。Kubernetes 用 StatefulSet 解决了有状态应用编排的问题&#xff0c;本文我们就来…

设计模式-创建型-原型模式-prototype

工作经验类 public class WorkExperience implements Cloneable {private String workDate;private String company;public void setWorkDate(String workDate) {this.workDate workDate;}public void setCompany(String company) {this.company company;}Overridepublic Ob…

【35分钟掌握金融风控策略21】贷前额度策略

目录 贷前策略审批流程和统一额度管理 贷前策略审批流程 统一额度管理 预授信策略 贷前策略审批流程和统一额度管理 贷前包含了多个风控场景&#xff0c;这些风控场景的策略在执行时是否存在先后顺序呢&#xff1f;在贷前&#xff0c;除上述主要的风控场景&#xff0c;还有…

2024年4月12日饿了么春招实习试题【第三题】-题目+题解+在线评测,2024.4.12,饿了么机试【Kruskal 算法, 最小生成树】

2024年4月12日饿了么春招实习试题【第三题】-题目题解在线评测&#xff0c;2024.4.12&#xff0c;饿了么机试 &#x1f3e9;题目一描述&#xff1a;样例1样例2解题思路一&#xff1a;[Kruskal 算法](https://baike.baidu.com/item/%E5%85%8B%E9%B2%81%E6%96%AF%E5%8D%A1%E5%B0%…

【第19章】spring-mvc之全局异常处理

文章目录 前言一、全局异常处理1. 前端2. 后端 二、常见错误页1.增加界面2.web.xml3.异常处理4.效果 总结 前言 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习&#xff0c;本文就介绍了机器学习的基…