指针进阶(详解)

news2024/11/19 21:24:22

指针进阶

  • 一.字符指针
  • 二.指针数组
    • 1.一次打印多个字符串
    • 2.模拟二维数组
  • 三.数组指针
    • 1.定义
    • 2.应用
  • 四.函数指针
  • 五.函数指针数组
  • 六.指向函数指针数组的指针
  • 七.回调函数

在这里插入图片描述

在开始这篇之前,前面有两篇指针初阶,如果需要的话可以去看看哟!指针初阶1,指针初阶2

一.字符指针

在这里插入图片描述

对于一个字符串,那么指针又该如何指向呢?

在这里插入图片描述

毫无疑问p里存的是地址,那它存了abcdefg的所有地址吗?当然不是,因为它根本存不下(一个指针在32为机器下只有4个字节,如果不太明白可以看看指针初阶)。实际上,它存的是首字符a的地址。字符串在内存里是连续存放的,所以只需要找到首元素地址就可以啦。ps:这和数组很像,事实上处理字符串时也可以按照下标来处理。

在这里插入图片描述

追加一个小知识:字符串可以直接使用%s打印是因为它有\0作为结束标志。但如果全部是整数的话,没有结束标志就只能通过下标挨个打印。

一道面试题

在这里插入图片描述

在这里插入图片描述

首先,str1和str2是两个数组,需要开辟两个空间,而数组名代表首元素地址,空间不同首元素地址自然不同,故str1!=str2。但是str3和str4是指针变量,里面存的都是h的地址并且hello,bite是一个常量字符串永远不能被改变。所以此时编译器就会认为既然都一样且没法被改变,那么就只会开辟一个空间,str3和str4都指向同一空间,故str3==str4。(可以理解为编译器的一种规定)

二.指针数组

存放整形的数组->整形数组,存放字符的数组->字符数组,存放指针的数组->指针数组。

1.一次打印多个字符串

在这里插入图片描述

在这里插入图片描述

我们如何打印呢?很简单,因为数组内每个元素存的都是各个字符串首元素地址,所以我们只需要依靠首元素地址就能打印出所有字符串。

在这里插入图片描述
在这里插入图片描述

2.模拟二维数组

在这里插入图片描述

它的打印需要使用两个for嵌套,因为它不能像字符串那样打印一串,这里其实也就是用一维数组模拟二维数组(但不同的是二维数组每一行每一列都是连续存放的,而这里每一行不一定连续)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三.数组指针

1.定义

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

追加个小知识:【】的优先级高于*所以别忘了加括号哦。

ps:如果pa先与*结合就说明是个指针,如果先于【】结合就说明是个数组。

pps:这里的&arr是整个数组的地址,也就是如果+1的话是跳过整个数组。注意与数组名区分开。

2.应用

1.强行使用

在这里插入图片描述

这样写实际上很别扭,当然实际上一般也没人会怎么写。所以它的真正作用体现在二维数组里。

2.正常使用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

一些练习

在这里插入图片描述

四.函数指针

指向函数的指针。

一段代码

首先,函数名=&函数,故函数名就是函数地址(如果需要验证的话,写一个函数再用%p输出就可以了,这里就不再累述了)

在这里插入图片描述

分析这个指针的构成,首先是一个指针故pf应该先与*结合,其次指向一个函数,后面就应该接上(参数),最后该函数是int类型,故再前面写上int。将这3个部分串起来就是如上指针。

接下来使用pf指针调用Add函数。

在这里插入图片描述

在这里插入图片描述

首先对pf进行解引用,解引用后就是原函数。也就是*pf=Add,接下来是传参(参数1,参数2),这样就完成了调用功能。实际上,在调用时前面的星号是没有作用的,因为如我们平常调用函数Add(2,3),pf里存的本身就是Add,所以不需要解引用。

在这里插入图片描述

代码一

在这里插入图片描述

这道题的关键就是把0当成地址来看。

在这里插入图片描述

该代码是一次函数调用,调用0地址处的函数

ps:以上代码出自c语言缺陷与陷阱

代码二

在这里插入图片描述

依然从名字signal入手。

在这里插入图片描述

1.该代码是一次函数的声明。
2.声明的函数名字是signal
3.参数有两个,第一个是int类型,第二个是函数指针类型
4.signal函数的返回值是一个函数指针

五.函数指针数组

数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,比如:int arr[10];数组的每个元素是int。那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?

在这里插入图片描述

使用:简单的计算器

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:加法      2:减法***\n");
		printf("*** 3:乘法      4:除法*** \n");
		printf("**********0.退出*********\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;
}

这个代码很简单就不多说了。实际上我们可以看到这个代码很冗长繁琐,如果在之后我们需要给计算器添加新的功能的话,毫无疑问case会加长,我们能不能有一种方法避免这种写法呢?

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(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //使用数组去除冗长的调用
	while (input)
	{
		printf("*************************\n");
		printf("*** 1:加法      2:减法***\n");
		printf("*** 3:乘法      4:除法*** \n");
		printf("**********0.退出*********\n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if (0 == input){
			printf("退出程序。\n");
			break;
		}
		if ((input <= 4 && input >= 1)){
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);
		}
		else
			printf("输入有误\n");
		printf("ret = %d\n", ret);
	}
	return 0;
} 

使用函数指针数组的前提是所有的函数类型都相同,都是两个参,参数类型都是int,返回值都是int。

六.指向函数指针数组的指针

其实本质上就是一个数组指针,只不过这个数组的类型是一个函数指针类型数组。

在这里插入图片描述

要分辨类型,需要先看与哪个操作符结合。

一些练习

在这里插入图片描述

七.回调函数

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

应用例子qsort函数,由于篇幅比较大,将其放到了下一篇博客里qsort函数

在这里插入图片描述

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

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

相关文章

网络安全等级保护确定定级对象

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 网络安全等级保护确定定级对象 信息系统 定级对象的基本特征 作为定级对象的信息系统应具有如下基本特征&#xff1a; 具有确定的主要安全责任主体&#xff1…

【MySQL进阶教程】SQL优化

前言 本文为 【MySQL进阶教程】SQL优化 相关知识&#xff0c;下边将对主键优化&#xff0c;order by优化&#xff0c;group by优化&#xff0c;limit优化&#xff0c;count优化&#xff0c;update优化等进行详尽介绍~ &#x1f4cc;博主主页&#xff1a;小新要变强 的主页 &am…

利用Python为女神制作一个专属网站

快跟随小编一起学习一下如何利用Python语言制作一个专属的网站送给女神吧&#xff01; 如觉得博主文章写的不错或对你有所帮助的话&#xff0c;还望大家多多支持呀&#xff01;关注、点赞、收藏、评论。 目录如觉得博主文章写的不错或对你有所帮助的话&#xff0c;还望大家多多…

1995-2019年全球清廉指数

1995-2019年全球清廉指数 1、时间&#xff1a;1995-2019年 2、来源&#xff1a;透明国际&#xff08;Transparency International&#xff09; 3、区域&#xff1a;全球170多个国家 4、指标说明&#xff1a; 清廉指数&#xff08;Corruption Perceptions Index&#xff0c…

【自学C++】C++ short

C short C short教程 C 中的 short 用来表示一个 整数&#xff0c;也可以叫做短整型&#xff0c;如果我们需要表示的整数比较小&#xff0c;那么我们可以使用 short 来定义&#xff0c;这样可以节省系统资源。 C short定义详解 语法 short int varname value; short varn…

【django】关联模型类中数据的增删改查操作总结

文章目录一、多对一正向操作1、改方法一方法二2、删3、查反向操作案例1&#xff1a;查询百度渠道下的所有学生信息案例2&#xff1a;新增一个百度渠道下的学生1、增直接创建Student对象2、改方法一&#xff1a;add()案例1&#xff1a;将s1,s2,s3添加到百度渠道中方法二:替换对象…

【Java】遨游在多线程的知识体系中(二)

前言&#xff1a;一、分析上篇多线程不安全原因1. count 操作是三个步骤&#xff0c;load add save2. 多个线程之间的调度是无序的&#xff0c;两个线程的上述三个操作可能存在多种不同的相对顺序3. 线程针对变量的修改不是原子的4. 内存可见性5.指令重排序二、synchronize 关键…

Java中clone的浅拷贝和深拷贝区别以及方法详解

克隆定义 在 Java 中&#xff0c;克隆是创建原始对象的精确副本的过程。它本质上意味着能够创建一个与原始对象具有相似状态的对象。 复制对象&#xff0c;首先要分配一个和源对象同样大小的空间&#xff0c;在这个空间中创建一个新的对象。 new对象和clone区别 使用new操作符创…

Python批量采集无水印短视频内容

前言 短视频流行起来可不是一年两年了&#xff0c;现在很多年轻人都在玩短视频&#xff0c;有些的单纯就是看看&#xff0c;而有些的就是自己发视频 我每天刷视频&#xff0c;一刷就停不下来&#xff0c;应该还是有蛮多人跟我一样的吧 那有没有想法用自己所学的python知识&a…

Linux管道——进程间通信(匿名管道、命名管道)

文章目录一、进程间通信1.1 进程间通信的概念1.2 进程间通信的目的1.3 进程间通信的本质1.4 进程间通信的分类二、管道2.1 匿名管道① 匿名管道的使用场景② 匿名管道实现通信的原理③ 创建匿名管道 pipe函数④ fork共享管道⑤ 匿名管道的五个特点⑥ 匿名管道的四种特殊情况2.2…

开发模型和测试模型,考点归纳,你都记住了吗?

目录 前言 一、开发模型 1.1、瀑布模型 1.2、螺旋模型 1.3、迭代模型和增量模型 1.4、敏捷模型 敏捷开发最流行的方式——scrum模型 二、测试模型 2.1、V模型 2.2、W模型&#xff08;双V模型&#xff09; 前言 对于模型&#xff0c;需要重点掌握特点&#xff0c;缺点&…

模板编程:constexpr +特例化 判断质数

重点&#xff1a; 1.constexpr 函数支持在编译期间完成计算 2.特例化是模板中一种定义 using namespace std;//编译期进行判断 constexpr bool isPrime(unsigned int p) {for (unsigned int d2;d<p/2;d){if (p % d 0){return false;}}return p > 1; }template<int…

python爬虫入门

基础知识 HTTP协议 我们浏览网页的浏览器和手机应用客户端与服务器通信几乎都是基于HTTP协议&#xff0c;而爬虫可以看作是一个另类的客户端&#xff0c;它把自己伪装成浏览器或者手机应用客户端&#xff0c;按照自己的逻辑贪婪的向服务器索取数据&#xff0c;如何向服务器索…

【实操篇】Linux的网络环境及其配置

目录 ●Linux网络环境原理图&#xff08;NAT模式&#xff09; ●虚拟网络编辑器对虚拟网卡ip进行修改&#xff08;VMnet-&#xff09; ●查看网关( VMnet8->WLAN) ●Linux网络ip配置 1.修改配置文件去获取固定ip 2.自动获取ip连接网络 ●Linux网络环境原理图&#xff…

【vue2】计算属性(computed)与侦听器(watch)详解

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;计算属性与侦听属性的用法 目录&#xff08;文末有给大家准备好的Xmind思维导图&#xf…

JAVA单商户商城系统源码,前(vue)后(SpringBoot)端分离,支持多平台(h5,小程序,app)

前言 完整代码下载地址&#xff1a;JAVA单商户商城系统源码 linjiashop 是一个基于Spring Boot和Vue.js的web商城系统 linjiashop 包含了商城的后台管理系统,手机h5&#xff0c;小程序版本 linjiashop 采用web-flash作为底层基础框架搭建&#xff0c;开发过程遇到问题请多阅…

Js中闭包的概念和具体使用

前言闭包在js里面是一个比较抽象的概念,但在面试里,是一个必问的话题,往往面试官希望你列举一些使用闭包的例子或手写一个闭包闭包,简单一句话讲就是能够读取其他函数内部变量的函数,当需要函数内容部的变量被外部的代码所访问时那闭包就非常有用了的,如今,很多框架里面的高级特…

Spring整合Mybatis和Junit

文章目录1 Spring整合Mybatis环境搭建整合步骤使用的注解详解2 Spring整合Junit整合Junit步骤使用的注解详解1 Spring整合Mybatis 大体需要做两件事&#xff0c; 第一件事是:Spring要管理MyBatis中的SqlSessionFactory 第二件事是:Spring要管理Mapper接口的扫描 具体该如何实现…

6.Isaac教程--在 C++ 中开发 Codelet

在 C 中开发 Codelet 本教程的目标是用 C 开发两个小码&#xff1a;第一个实际上是一台“ping”的机器&#xff0c;而第二个侦听并摄取“ping”消息。 对于本教程&#xff0c;不需要外部依赖项或特殊硬件。 文章目录在 C 中开发 Codelet创建新应用程序为应用程序创建一个新目录…

【Linux】Linux的基本指令(一)

文章目录1、ls 指令2、pwd 命令3、cd 指令4、touch 指令5、mkdir 指令6、rmdir和rm 指令7、man 指令8、cp 指令9、mv 指令10、cat11、echo(输出&#xff0c;输入&#xff0c;追加重定向)12、wc13、more14、less1、ls 指令 语法&#xff1a; ls[选项][目录或文件] 功能&#xff…