C语言(指针)1

                       Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,关注+收藏,欢迎欢迎~~     

                        💥个人主页:小羊在奋斗

                        💥所属专栏:C语言   

        本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为同样是初学者的学友展示一些我的学习过程及心得。文笔、排版拙劣,望见谅。 

                                1、内存和地址

                                                1.1内存

                                                1.2编址

                                2、指针变量和地址

                                                2.1取地址操作符和指针变量

                                                2.2解引用操作符 “ * ”

                                                2.3指针变量的大小

                                3、指针变量类型的意义

                                                3.1指针的解引用

                                                3.2指针 +- 整数

                                                3.3void *类型

1、内存和地址 

        1.1内存

        理解内存和地址,我们可以把它们类比为宿舍楼和房间编号。宿舍楼有大有小,大一点的宿舍楼较小一点的宿舍楼可以居住更多的学生,同样的,计算机的内存也是有大有小,我们常见的有8G、16G、32G等,更大的内存能存储更多的信息。

        宿舍楼的编号是为了更方便的管理学生,为学生提供便利,同样的,为了更高效的管理内存,内存也被划分为一个个小的内存单元,每个内存单元的大小是一个字节,一个字节中有8个比特位。

        这里需要注意一点,单一个比特位是没有地址的,只有一个内存单元才有一个地址,这就像我们在学校住宿舍,学校基本不可能给我们一人一个宿舍,而是4人或6人寝。

        所以,每个内存单元,就类似于学生宿舍,一个 “字节宿舍” 里能住 “8个比特同学” 。宿舍有门牌号,内存单元也有 “门牌号”,就是内存地址编号,有了这个内存单元的编号,CPU就能快速的找到这个内存空间,对其相应的操作。

        生活中,门牌号叫地址,在计算机中内存单元的编号也叫地址。在C语言中还给地址起了一个新的名字,叫做指针。可以粗略的认为:地址就是指针,指针就是地址

         1.2编址

        CPU访问某个内存单元,先要知道其地址,因为内存空间很大,所以需要给内存单元编址。编址并不是把每个字节的地址记录下来,而是通过硬件来实现,就像琴键上并没有标上这个键是什么音,但是学过钢琴的人却能弹奏曲子,这是因为制造这架钢琴前其界内就约定了每个键该是什么音,计算机编址也是如此。

        我们可以简单地理解,32位机器有32根地址总线,每根线有两个形态,0或1(电脉冲的有无),一根线能表示两种信息,那么32根线就能表示2的32次方种信息,这个数还是非常大的。地址信息被下达给内存,CPU在内存上就能找到该地址对应的数据,将数据通过数据总线传给CPU内的寄存器。

        计算机中并没有魔法,其内有很多的硬件单元,硬件单元之间协同工作,要想协同,就要进行数据传递。但硬件与硬件之间是相互独立的,怎么通信呢?答案很简单,就是用线连起来。而CPU和内存之间也是要交互数据的,两者也要用线连起来。本节只关心地址总线。 

2、指针变量和地址 

        2.1取地址操作符和指针变量 

        如上,创建变量实质上是向内存申请一块内存空间,上面我们申请了4个字节的空间来存20这个值。可以看到右边0x010FF9B0~0x010FF9B3就是我们申请到的4个字节的地址,每个字节都有地址,存放了14 00 00 00(16进制)这个值(10进制为20)。 

        看了上面的内容,这里有一个提问,变量 “a” 对于上面代码的执行有什么作用?其实仔细想想好像也没有什么作用。变量的名字仅仅是给程序员看的,编译器不看名字,编译器是通过地址找内存单元的

        我们给变量a申请了4个字节的地址,通过取地址操作符 “&” 我们可以拿到地址值。但是a占4个字节的空间,地址有4个, “&” 操作符拿到的是4个还是其中的一个呢?

        可以看到,“&” 操作符只取到了最小的一个地址,不过当我们拿到这个 “头” 的时候,就能顺藤摸瓜找到其他地址。

        值得一说的是,当 “&” 是单目操作符的时候,它是取地址操作符;当 “&” 是双目操作符的时候,它是按位与操作符。

        当我们拿到变量a的地址后,如果我们想把变量a的地址存起来,就需要再创建一个变量,而用来存放地址的变量,就叫指针变量。 既然是变量,就要有一个类型来创建,指针变量的类型取决于它所指对象的类型。

        这里定义了一个整型的指针变量 “pa”,注意是 “pa” 而不是 “ *pa ”,指针变量 “pa” 是用来存放地址的。 pa是指针变量的名字,而int *是pa的类型。* 表示pa是指针变量,int表示pa指向的对象的类型为int。* 靠近int还是靠近pa是无所谓的,但是建议靠近pa,具体原因在后面的文章中会有解释。

        上面为指针变量pa与整型变量a比较。 

        还有一点需要注意,当我们写出 int *p = 100;这样的表达式的时候,就把100也看作了一个地址。p作为一个指针变量,在它眼里给它的值都是地址。

 2.2解引用操作符“ * ”

        当 “ * ” 是单目操作符的时候,它是解引用操作符,也叫间接访问操作符;当 “ * ” 是双目操作符的时候,它是乘法操作符

        将变量a的地址存到指针变量pa中,可以在某些时候通过pa来找到a或者间接的操作a。这就像我们的朋友告诉了我们他的宿舍门牌号,我们记下来后,想去找他的时候就可以快速地找到他。那该怎么找a呢?用解引用操作符 “ * ” :

        *pa就相当于a。 我们用*pa间接的改变了a的值。

        那这么做的意义是什么呢?想改变a的值我们直接改不就可以了,为什么还要用*pa来间接的改呢?

        这么做的意义其实是很大的。打个比方,一个杀手在常年的任务中越来越厉害,他就成立了一个杀手组织做了老大,他作为老大是很重要的人物,那这个时候一些任务他就不方便亲自出手了,交给手下就可以完成任务。指针在上面代码中的意义也是如此,使得代码更加灵活。

        作为C语言的灵魂,指针是C语言中功能最强大的机制,在后续的学习中就会慢慢地理解其中的含义。

         2.3指针变量的大小

        在探讨指针变量的大小前我们应该先搞清楚指针变量是干什么的。指针变量,是为了存放地址而创建的一个变量,那么指针变量的大小有多大,是不是就取决于这个地址有多大。

        在32位机器中,有32根地址线,32根地址线有32个0或1的数字信号,把这32根地址线产生的2进制序列当作一个地址,那么一个地址就要32个比特位,也就是4个字节。所以,指针变量的大小就应该是4个字节。同样的道理,在64位机器中,指针变量的大小就应该是8个字节。

         有没有注意到我在描述指针变量大小的时候并没有明确说明指针变量的类型,而是总体的说指针变量的大小。实际上,指针变量的大小与指针的类型没有关系。地址是由地址总线传过来的,而地址总线的数量是确定的,32根地址总线或64根地址总线,对应4个字节和8个字节的大小,不管是整型变量的地址还是字符型变量的地址都是地址,所以大小是一样的。

        还有一点,前面说了 “&” 操作符取到的只是首地址(最小的地址),所以不管地址是1个字节还是4个字节还是8个字节,只要取出首地址就可以了。

        关于指针变量的大小和不同类型变量所占空间大小,我们可以抽象地想象为一个固定大小的盒子装不同大小的小盒子,大小就那么大,不用白不用嘛。

3、指针变量类型的意义

        既然指针变量的大小与类型没有关系,那为什么还要有不同的指针类型呢?

        在某些情况下,指针类型还是有很大意义的。

         3.1指针的解引用

        这里来举一个例子探讨指针变量类型的意义。

        如果对调试还不太熟悉可以看这篇文章 —> VS调试技巧

        观察下面代码在调试时内存中的变化: 

        我们先给a赋值为0x11223344(16进制),在内存窗口可以看到,然后再通过*pa将a该为0,可以看到内存中也发生了相应的改变。

        既然指针变量的大小都是一样的,与指针的类型没有关系,那我们用char *类型来接收a的地址按理说应该也可以,而且&a取出来的地址都是首地址(一个内存空间,大小是1个字节),好像没什么问题。从上面调试的结果来看确实放进去了0x11223344这个值。

        我们接着调试看一下结果:

        好像跟我们想的不一样,执行完 *pa = 0;这条语句后只是把最小的地址(一个内存单元)中的值该为了0。这是为什么呢?

         因为,指针类型决定了对指针解引用的时候有多大的权限,也就是一次能操作几个字节这就是指针变量类型的意义。比如:char *类型的指针解引用访问一个字节,int *类型的指针解引用访问4个字节。

        3.2指针+-整数

         观察下面的代码:

        跟我们想的一样,&a、pa、pc的值是一样的,但当我们给&a、pa、pc加一个整数1的时候得到了不一样的结果,通过观察,&a和pa的值都增加了4, 而pc的值只增加了1。其中的原因还是和3.1中一样,我们再来通过下面的图解释一下:

        可以理解为他们走的格数不一样,一个格子就是一个内存单元也就是1个字节空间,a和pa一个是int类型一个是int *类型,所以它们走4个格子;而pc是char *类型,所以它走1个格子。 

        减一个整数也是同样的道理。 

         3.3void *类型

        在指针类型中有一种特殊的类型是 void * 类型的,为无具体类型的指针(泛型指针),这种类型的指针可以用来接收任意类型的地址。但是有一定的局限性,void *类型的指针不能直接进行指针的 +- 整数和解引用运算。了解了上面的内容,这其中的原因相信我们已经心知肚明。

        其实,我们 char *pc = &a;是有问题的,&a取出的地址毕竟是int *类型。虽然能正常运行,但是编译器也有相应的警告:

        但是我们用void *去接受就没有任何问题: 

        虽然void *类型的指针不能直接进行解引用操作也不能 +- 整数的操作, 但是当我们不知道别人给我们传的地址是什么类型的时候,我们就可以放心地去用void *来接收,这就是它的作用。

        一般void *类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果,使得一个函数来处理多种类型的数据。在后面的文章中会深入探讨。 

                                          点击跳转主页—> 💥个人主页小羊在奋斗

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

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

相关文章

用python写个控制MicroSIP自动拨号和定时呼叫功能(可用在小型酒店叫醒服务)

首先直接上结果吧,MicroSIP 助手,控制MicroSIP自动拨号,定时呼叫的非常实用小工具! 在使用MicroSIP 助手之前,我们需要了解MicroSIP是什么,MicroSIP是一个SIP拨号软件,支持注册任意SIP平台实现拨…

Linux学习笔记:信号

信号 在Linux中什么是信号信号的产生方式硬件产生的信号软件产生的信号异常产生的信号 进程对信号的处理信号的保存信号方法更改函数signal信号处理的更改恢复默认信号忽略 信号的管理信号集 sigset_t对信号集的操作 信号的捕捉过程 在Linux中什么是信号 在 Linux 系统中&…

Python中tkinter编程入门1

1 tkinter库简介 tkinter是Python的标准库,用来进行GUI(Graphical User Interface,图形用户界面)编程。 2 导入tkinter库 tkinter是Python默认的GUI库,因此,IDLE中已经包含了该库,使用时无需…

在uniapp中如何安装axios并解决跨域问题

目录 1、安装axios 2、导入 3、使用(发请求) 2.解决跨域问题 1.为什么要解决跨域问题? 2.前端如何解决跨域问题? 1、安装axios npm install axios 2、导入 在main.js中导入使用 import axios from axios; // 创建一个名…

男士内裤什么品牌质量好?男士内裤选购指南攻略分享

有很多小伙伴认为男士内裤只是穿在里面的,只要能穿就不讲究了。但实际上选择一些质量不好的男士内裤会让穿着舒适性十分不佳,同时还会因为不具备抗菌效果而滋生细菌,导致出现健康问题。 最近我也是深入研究了一番关于男士内裤,今天…

旺店通·企业奇门与金蝶云星空对接集成订单查询打通销售订单新增

旺店通企业奇门与金蝶云星空对接集成订单查询打通销售订单新增 对接源平台:旺店通企业奇门 慧策最先以旺店通ERP切入商家核心管理痛点——订单管理,之后围绕电商经营管理中的核心管理诉求,先后布局流量获取、会员管理、仓库管理等其他重要经营模块。慧策…

该怎么发外贸开发信才能瞄准大客户?

1.要知道80%的业务源自于大客户,要合理利用自己的时间。其实我自己发邮件一直都是粗发模式,效果也还可以,主要是因为我的客户都是展会上的,所以拒收和失败率会很低,而且客户意向度一直很高,但是花费的时间精…

泉州晋江厦门拉货最便宜的7个方式,建议收藏

众所周知,搬家、拉货的时间长、距离长,运费也比较贵。面对不菲的费用,很多人会比较谨慎,先网上搜搬家攻略,一番对比以后,找到最便宜的运输方式。那怎么运输最便宜最放心呢? 方式一:找…

[MDK] 介绍STM32使用C和C++混合编程的方法

目录 [MDK] 介绍STM32使用C和C混合编程的方法前言业务场景步骤1基础工程步骤2写代码步骤3添加cpp文件步骤4配置与编译上机现象后记 [MDK] 介绍STM32使用C和C混合编程的方法 前言 搞单片机编程大多数还是使用MDK编程,自己对MDK这个软件也比较熟悉,在网络…

【RAG 论文】Dense X 检索:将“命题”作为检索粒度

论文:Dense X Retrieval: What Retrieval Granularity Should We Use? ⭐⭐⭐⭐ Code: github.com/ct123098/factoid-wiki 文章目录 一、论文速读二、命题(Proposition)三、FactoidWiki四、实验及分析4.1 Passage Retrieval 任务4.2 Open-Do…

前端css中径向渐变(radial-gradient)的使用

前端css中径向渐变的使用 一、前言二、主要内容说明(一)、径向渐变的形状1.椭圆形渐变(ellipse),源码12.源码1运行效果3.圆形渐变(circle),源码24.源码2运行效果 (二&…

遇到螺纹连接过程中的软连接,怎么办?——SunTorque智能扭矩系统

智能扭矩系统-智能拧紧系统-扭矩自动控制系统-SunTorque 在螺纹连接过程中遇到软连接时,首先需要明确软连接的概念及其特点。软连接通常指的是在螺栓拧紧过程中,由于紧固件与被连接件之间的材料、表面状况或装配工艺等因素,导致拧紧力矩不能…

分布式关系型数据库管理系统 OceanBase 安装和配置教程

🌊 分布式关系型数据库管理系统 OceanBase 安装和配置教程 🚀 博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝…

Kubernetes核心概念基本操作

1.1 Namespace命名空间 1.1.1 Namespace核心概念 Kubernetes 的 Namespace(命名空间)是一种用于创建逻辑隔离分区的机制,它的主要作用是用来实现多套环境的资源隔,它允许用户在同一个物理集群中模拟出多个虚拟集群的效果。以下是…

APP广告变现:自刷的秘密与规则

在移动互联网时代,广告已成为众多APP盈利的主要方式之一。对于开发者和运营者而言,如何通过广告变现提高收益是他们必须关注的问题。然而,在众多的变现方法中,“自刷广告”这一概念可能让一些人感到迷惑。实际上,只要在…

在Mars3d实现cesium的ImageryLayer自定义瓦片的层级与原点

需要自定义瓦片层级和原点,所以需要自己写第三方图层,但是之前写的很多方法,图层控制和显隐以及透明度,需要跟之前的交互一直,改动量太大的话不划算,所以直接看Mars3d的layer基类,把重写的image…

python词云图背景颜色修改

python词云图背景颜色修改 词云图介绍wordcloud介绍修改背景颜色 词云图介绍 词云图(Word Cloud)是一种文本数据的可视化表示形式,它通过字体大小、颜色、布局等视觉元素来展示文本中不同词汇的频率或重要性。词云图中,出现频率高…

怎么清理服务器的C盘?

有时候我们经常会遇到C盘被占满的情况,C盘被占满的原因有很多,下面我们就来分析下有可能导致C盘占满的原因: 第一种情况:中毒 打开服务器任务管理器选择进程,并且勾选显示所有用户的进程,我们可以点击映像…

PHPStudy 下载PHP提示“当前网络不稳定,下载失败”

错误信息 当前网络不稳定,下载失败 获取下载链接失败,请检查网络 假查网络 问题原因 xp.cn服务器的网络不稳定,不是你电脑的网络问题。 解决办法 第一步:下载现成的PHP文件 直接下载现成的文件,放到php目录。 将…

FlashAttention(flash-attn)安装

FlashAttention(flash-attn)安装 Flash Attention是一种注意力算法,用于减少这一问题,并更有效地缩放基于转换器的模型,从而实现更快的训练和推理。标准注意力机制使用高带宽内存(HBM)来存储、…