手撕指针第一页

1.  理解内存和地址

1.1  内存

内存,顾名思义就是电脑用来存储数据的,当CPU(中央处理器)在工作时,不仅需要从内存中拿取数据也需要将数据放入内存当中,当把内存引入到现实当中,就像学校里面的宿舍楼一样,每个宿舍楼有许多间宿舍,每一间宿舍住着8个人,内存里面有许多的内存单元,每一个内存单元就像一间宿舍一样,而这个内存单元叫做字节,每个字节又相当于8个比特位,每一个比特位对应8人间的每一个人。

1.2  地址

宿舍有宿舍的地址,每一个内存单元也有自己的地址,宿管阿姨可以通过寝室号找的你的宿舍,而程序员也就可以通过地址找到内存里面存储的数据,在C语言中地址也叫作指针。

                                            内存单元的编号==地址==指针

2.  指针变量

2.1  取地址操作符(&)

&:取地址操作符是将一个变量的地址取出来

当我们创建变量时,就会向内存申请一块内存空间,就像我们在外住宿时就会去酒店开一间房间,但我们要去房间住宿时,前台会给我们房间号找到这个房间,同样的,当我们需要将一个数据放到一块内存空间里面时,就要通过&(取地址操作符)找到这个变量的地址

我们可以通过监视窗口看见&a的值,再通过内存窗口发现a的地址和&a的值是一样的

所以&(取地址操作符)的作用就是获得一个变量的地址,然后我们通过这个地址将数据存储到变量里面

2.2  如何创建一个指针变量

简单介绍一下指针变量是什么:

指针变量就是一个存放指针(也就是地址)的变量

创建指针变量的基本格式:

解释:

                左边分别是整形变量,字符变量,浮点型变量。右边是他们对应的指针变量。

这⾥p1,p2,p3左边写的是 int*,char*,double* , * 是在说明p1,p2,p3是指针变量,⽽前⾯的 int ,char,double是在说明p1,p2,p3指向的是整型(int),字符型(char),浮点型(double)类型的对象

2.3  解引用操作符(*)

我们将地址保存起来,未来是要使⽤的,那怎么使⽤呢?
在现实⽣活中,我们使⽤地址要找到⼀个房间,在房间⾥可以拿去或者存放物品。
C语⾔中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这⾥必须学习⼀个操作符叫解引⽤操作符(*)

            1.(*)解引用操作符对比生活,他就像一把钥匙,当我们知道一个房间号(地址),想要拿到里面的东西,就需要一把钥匙把房间打开才能拿到里面的东西,当然出来从里面拿东西也可以将里面的东西腾出来,放入新的东西。

            2.printf("%d",*p);p里面存放着a的地址,我们用钥匙(*)打开这个地址,就可以看见里面存放的东西也就是100

            3.*p=10;就是将10放入到p所指向的地址里面去,从而改变了a的值

2.4  指针变量的大小

我们知道,32位机器下有32根地址总线,每一根脉冲信号为0或1,而这些脉冲信号组成的二进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储,如果用指针变量来存储一个地址,至少需要4个字节才能存储,同理在64位机器下需要8个字节才能存储这些地址

小结:

• 32位平台下地址是32个bit位,指针变量⼤⼩是4个字节
• 64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
• 注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是       相同的。

3.  指针变量的意义

既然各种各样的指针在相同平台下的大小都是相同的,为什么还要弄这么多的指针类型,用一个指针不就行了吗?那么接着往下看,你就会知道设计师为什么这么设计。

3.1  指针的解引用

用例1:

当我们创建一个整形变量,并且给他赋0x11223344(因为8位的16进制数刚好可以占满4个字节),当用整形指针来接收a的地址,再将p解引用再赋值为0时,通过内存窗口可以看见,4个字节全部被修改为0.

用例2:

但我们用字符指针来接收a的地址时,再将p解引用再赋值为0时,通过内存窗口可以看见,发现只有第一个字节被修改为0

结论:

         指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。
⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节

3.2  指针加减整数

通过代码我们可以发现,char*类型的指针+1跳过一个字节,而int*类型的指针+1跳过4个字节,指针的类型决定了指针向前或者向后走一步能跳过几个字节

3.3  void*类型的指针

3.3.1  void类型

1.void类型和char,int,double等类型的区别是:void类型不能用来声明变量

   下面这种声明变量是错的

void a=10;

2.void类型也常常出现在函数返回值,表示该函数无返回值

void compar(参数1,参数2);

3.void类型也可以出现在函数参数里

int fun(void);          int fun();

这两种写法是等价的,都表示不需要给函数传递参数

3.3.2  void*指针

void*指针也叫做泛型指针(无具体类型的指针),他可以用来接收各种类型的指针,但是他不能直接进行指针加减整数和解引用的操作,需要进行强制类型转换才能进行指针加减整数和解引用的操作

两段代码对比,用void*类型的指针来接收int*类型的指针是可以的,但是直接对p解引用是错误的,我们需要将void*类型强制转换为int*类型才能使用

⼀般 void* 类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得一个函数来处理多种类型的数据,在下面讲到qsort函数时,我们会对void*的使用有更深的了解

4.  指针的运算

4.1 指针加减整数

指针加减整数表示指针可以跳过几个字节

数组在内存中是连续存放的,我们将3的地址给到p,当我们对p进行加一操作时,可以发现在3地址的基础上加上了4个字节,得到了4的地址,从而访问到了4,同理,1,2,5也是同样的原理

4.2 指针减指针

指针加减整数我们知道得到的还是指针,那么指针减指针得到的就是整数,这个整数也就是两个指针之间相差多少个元素

arr[0]和arr[5]之间相差20个直接,而int*类型加1跳过4个直接,所以p1-p为5

有指针减指针,有指针加指针吗?

看看下面这两段代码

两个指针相加的到的是指针还是整数?答案是都不是,这种写法是错误的。

4.3 指针的关系运算

指针的关系运算简而言之就是指针比大小,指针不都是地址吗?地址也有大小吗?答案是地址也有大小

我们可以看出p1的值比p的大,而这两个值分别是a[3]和a[0]的地址,所以指针是可以比较大小的

5.  野指针

5.1 常见的三种野指针

  1.未进行初始化的指针

创建了int*类型的指针,但是并没有给p赋值,所以不知道p指向何处,故p为野指针

2.越界访问的指针

第11个数打印的是随机值,指针指向的地址超出arr,p就是野指针

3.指针指向的空间被释放掉

在test()里面创建了一个n变量,返回n变量的值,用p来接收,但是当&n返回时,也就是出test()函数是,n变量就已经被销毁了,虽然还能打印出n的值,但是p是一个野指针。

5.2 如何规避野指针

1.创建指针变量时,对指针进行初始化,如果指针没有明确的指向时,可以将指针初始化为NULL,NULL是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址会报错

2.防止指针越界访问,我们向内存申请了多少空间,那就让指针在申请的空间内进行使用,不要超出范围访问

3.当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问,同时使⽤指针之前可以判断指针是否为NULL

4.避免返回局部变量的地址

6.传值调用和传址调用

我们在写自定义函数时常常会进行传参,参数可分为传值和传址

6.1 传值调用

这是一个交换函数,我们将实参传给形参,然后形参进行交换,最后发现x和y的值没有发生改变,这是因为当实参传给形参时,形参是实参的一份临时拷贝,当函数进行结束后,形参会被销毁,而在整个函数进行过程中一直是形参在参与运算,实参一点也没有参与,所以最后实参的值不会被改变,形参和实参分别占有不同的内存块,对形参的修改是不会改变实参的。

6.2 传址调用

我们将swap的参数部分改为指针,然后通过指针去交换x和y的值,发现可以将两者进行交换,这是因为,我们通过地址直接对x,y进行修改,就算局部变量销毁,也不会影响x和y的值,让函数和函数外面的变量建立起联系,也就是函数的内部可以直接操作函数外部的变量。

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

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

相关文章

如何恢复已删除的华为手机图片?5 种方式分享

不幸的现实是,华为的珍贵时刻有时会因为意外删除、软件故障或其他不可预见的情况而在眨眼之间消失。在这种情况下,寻求恢复已删除的图片成为个人迫切关心的问题。 本文旨在为用户提供如何从华为恢复已删除图片的实用解决方案。我们将探索五种可行的方法…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RowSplit容器组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RowSplit容器组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、RowSplit容器组件 将子组件横向布局,并在每个子组件之间插入一…

CentOS/Fedora/Ubuntu/Debian 系统 wget 命令

wget 是云服务器安装环境和面板常用下载命令。下载软件或从远程服务器下载备份到本地服务器,也可以使用 wget 把文件下载到云服务器上。 VPS wget 命令最常用使用方法如下: 安装 wget 一般来说 wget 命令是系统自带的,方面安装环境和面板&…

【Python】可变数据类型 不可变数据类型 || hash

🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

神经网络算法(带你了解 原理 实践)

目录 引言 一、神经网络的历史背景与重要性 二、神经网络算法在现代机器学习中的地位与应用 三、神经网络基础知识​编辑 (一)神经元模型与工作原理 (二)网络结构 (三)激活函数的作用与常见类型 四…

云原生架构设计:开放应用模型(OAM)的重要性与实践

在当今云计算时代,云原生架构已经成为许多企业追求的理想状态,在云原生架构设计中,开放应用模型是至关重要的一部分。本文灸哥将和你一起探讨开放应用模型的概念、意义以及实践方法,以帮助大家更好地理解和应用云原生架构中的开放…

guava的使用

对数组操作前判断是否会越界&#xff1a; List<String> s new ArrayList<>();System.out.println(Preconditions.checkElementIndex(2,s.size(),"下标长度超过了")); 是否为空 String s null;System.out.println(Preconditions.checkNotNull(s)); 判空…

如何使用LEAKEY轻松检测和验证目标服务泄露的敏感凭证

关于LEAKEY LEAKEY是一款功能强大的Bash脚本&#xff0c;该脚本能够检测和验证目标服务中意外泄露的敏感凭证&#xff0c;以帮助广大研究人员检测目标服务的数据安全状况。值得一提的是&#xff0c;LEAKEY支持高度自定义开发&#xff0c;能够轻松添加要检测的新服务。 LEAKEY主…

HUAWEI华为MateBook D 14 2022款 12代酷睿版集显(NbF-16)工厂模式原厂Windows11预装OEM系统,含F10智能还原功能

系统下载链接&#xff1a;https://pan.baidu.com/s/1kgJvwSq5eOdme7J9PDXIxQ?pwdxvz8 提取码&#xff1a;xvz8 华为笔记本电脑原装出厂系统工厂安装包&#xff0c;含F10功能、系统自带所有驱动、系统属性专属联机支持标志、Office办公软件、华为电脑管家等预装程序&#xf…

练习 5 Web [GXYCTF2019]BabyUpload

[GXYCTF2019]BabyUpload 猜测直接上传txt会被过滤&#xff0c;提示“上传类型也太露骨了吧&#xff01;”按经验传入一个"muma.phtml" 提示过滤了“ph”相关的后缀 传入muma.jpg等图像格式&#xff0c;提示表明复原并检测了文件内容 审查文件后缀Context-type 不能…

机械臂中TCP配置

红色、绿色、蓝色箭头分别代表x、y、z三个方向

电脑解锁后黑屏有鼠标--亲测!!不需要重装系统!!

问题&#xff1a;上周电脑黑屏&#xff0c;只有鼠标&#xff0c;鼠标还不能右键&#xff01;&#xff01; 中招&#xff1a;win10系统最新版火绒安全 &#xff0c;那你有概率获得开机黑屏套餐一份。 原因是&#xff1a;火绒把我们的explorer删除了导致黑屏&#xff0c;这个文…

Java面试篇【并发编程·进阶】常见面试题(2024最新)

并发常见面试题进阶 1.synchronized synchronized关键字解决的是多线程之间访问资源的同步性&#xff0c;synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能被一个线程执行。 监视器锁&#xff08;monitor&#xff09;是依赖于底层的操作系统的 Mutex Lock来…

2024电子商务与互联网技术国际会议(ICECIT 2024)

2024电子商务与互联网技术国际会议&#xff08;ICECIT 2024) 一、【会议简介】 2024电子商务与互联网技术国际会议&#xff08;ICECIT 2024&#xff09;将于2024年在杭州举行。这是一个重要的学术会议&#xff0c;旨在汇集全球的专家、学者和业界领袖&#xff0c;共同探讨电子…

Python爬虫——Requests

目录 简介 基本使用​编辑 ​编辑 安装 一个类型和六个属性 请求类型 GET 代码示例 POST 代码示例 代理 古诗文网绕过验证码登录 总结 简介 Python的Requests库是一个用于发送HTTP请求的常用库。它提供了简单且人性化的API&#xff0c;使得发送HTTP请求变得非常容易。…

【MATLAB源码-第158期】基于matlab的海马优化算法(SHO)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 海马优化器&#xff08;Sea Horse Optimizer, SHO&#xff09;是一种近年来提出的新型启发式算法&#xff0c;其设计灵感来源于海洋中海马的行为模式&#xff0c;特别是它们在寻找食物和伴侣时表现出的独特策略。海马因其独特…

【Flink网络数据传输】OperatorChain的设计与实现

文章目录 1.OperatorChain的设计与实现2.OperatorChain的创建和初始化3.创建RecordWriterOutput 1.OperatorChain的设计与实现 OperatorChain的大致逻辑 在JobGraph对象的创建过程中&#xff0c;将链化可以连在一起的算子&#xff0c;常见的有StreamMap、StreamFilter等类型的…

[C语言]——分支和循环(1)

目录 一.if语句 1.if 2.else 3.分支中包含多条语句 4.嵌套if 5.悬空else问题 二.关系操作符 三.条件操作符 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是顺序结构、选择结构、循环结构&#xff0c;C语⾔是能够实现这三种结构的&#xff0c;其实我们如果仔细分析&a…

xinput1_3.dll丢失都有什么办法可以有效的解决、xinput1_3.dll导致游戏不能启动怎么办?

使用电脑的过程中是不是会遇到关于某个dll文件丢失的提示&#xff0c;今天想和大家聊的是xinput1_3.dll文件&#xff0c;如果电脑提示xinput1_3.dll丢失有什么办法可以有效的解决&#xff0c;解决办法都有哪些&#xff0c;如果xinput1_3.dll丢失会对电脑有什么影响。&#xff0…

8、Linux-软件安装:rpm和yum;配置yum阿里云镜像源

一、介绍 Linux安装软件有两种方式&#xff0c; ①rpm&#xff1a;安装已有的安装包&#xff0c;类似于Windows中双击exe的安装包程序 ②yum&#xff1a;拉取远程仓库的文件&#xff0c;类似于python的pip install 区别&#xff1a;假设软件A依赖软件B&#xff0c;软件B依赖…