展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 硬件相关 > 初识指针:我的学习笔记

初识指针:我的学习笔记

前言:谈及指针,大部分人只有一个感觉:太难学了,好抽象啊!但是,请不要着急,今天当你看完这一篇后,相信你肯定能够理解什么是指针了。1、内存和地址1.1理解内存和地址在介绍指针前,我们需要先了解什么是内存和地址。关于内存和地址,生活中有一个例子可以很好的解释它们比如说你住在一栋宿舍楼,大楼内有100个房间,但是房间并没有编号。这时,你的一个朋友来找你玩,如果想找到你,就得一个房间一个房间的寻找,这样效率很低。但是,如果我根据楼层和楼层的房间的情况,给每一个房间都编上号,比如:当有了门牌号,这时候你只需要将

本文目录
    前言:

    谈及指针,大部分人只有一个感觉:太难学了,好抽象啊!但是,请不要着急,今天当你看完这一篇后,相信你肯定能够理解什么是指针了。

    1、内存和地址1.1 理解内存和地址

    在介绍指针前,我们需要先了解什么是内存和地址。

    关于内存和地址,生活中有一个例子可以很好的解释它们

    比如说你住在一栋宿舍楼,大楼内有100个房间,但是房间并没有编号。这时,你的一个朋友来找你玩,如果想找到你,就得一个房间一个房间的寻找,这样效率很低。但是,如果我根据楼层和楼层的房间的情况,给每一个房间都编上号,比如:

    当有了门牌号,这时候你只需要将门牌号告诉你朋友,他就可以很快速的找到房间,找到房间里的你。

    如何将上面的例子抽象到计算机里呢?你可以理解宿舍楼就是内存,房间就是内存中的一个内存单元,房间里的你就是数据,而门牌号就是地址。

    所以内存就是存储数据的空间

    我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何高效的管理呢?

    cpu从内存中读取数据,就好比是你朋友要在宿舍楼里找到你,而你朋友找你,也只是在一个个房间寻找。大楼里的一个一个房间的划分,让人们对大楼内的面积能够充分利用,而计算机中也是如此。内存的空间只有8GB/16GB/32GB,因此对于内存的合理运用也变的很重要。

    计算机中把内存也划分为一个个的内存单元,每个内存单元的大小取1字节。

    (补充)计算机中常见的单位:

    一个bit可以存储一个2进制位的1和0

    地址(门牌号)

    内存(大楼)

    其中,每个内存单元,相当于⼀个学⽣宿舍,一 个字节空间里面能放8个比特位,就好比同学们住 的八⼈间,每个人是⼀个比特位。

    0xFFFFFFFF(16进制)

    1个字节

    0xFFFFFFFE

    1个字节

    1个字节

    每个内存单元也都有⼀个编号(这个编号就相当 于宿舍房间的门牌号),有了这个内存单元的编 号,CPU就可以快速找到⼀个内存空间。

    (内存单元)

    生活中我们把门牌号也叫地址,在计算机中我们 把内存单元的编号也称为地址,C语言中给地址起了新的名字叫:指针

    1个字节

    0x00000001

    1个字节

    0x00000000

    1个字节

    所以我们可以理解为:内存单元的编号 == 地址 == 指针

    1.2 理解编址

    生活中关于我们可以看到通过宿舍门上的门牌号,直接找到我们想去的地方。门牌号是真实存在与宿舍门上的。而内存中的地址我们该怎么理解呢?

    计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。

    这就像钢琴,吉他上面没有刻上“剁、来、咪、发、 唆、拉、西”这样的信息,但演奏者照样能够准 确找到每⼀个琴弦的每⼀个位置,这是为何?因为制造商已经在乐器硬件层面上设计好了,并且 所有的演奏者都知道。本质是⼀种约定出来的共识!

    有点抽象,举个例子:

    图书馆里有一排排的书架,每个书架又有一层层的格子,这些格子就好比内存中的存储单元。

    给每个格子编上号,也就是编址,就像是要给图书馆里的每个格子都贴上标签。

    那这个标签是怎么贴上去的呢?这就得靠图书馆的“硬件设计”了。

    比如说,书架的排列方式、格子的划分规则,就像是硬件的设计。

    想象一下,书架是固定的,它们的位置和大小决定了格子的位置和数量,这就好比硬件决定了内存有多少个可以存储数据的地方。

    然后,有一套专门的标记系统,就像特殊的机器或者装置,按照书架和格子的排列,给每个格子都印上编号,这就是通过硬件实现了编址。

    C:初识指针—学习笔记

    那硬件设计又是怎么实现的呢?

    首先,必须理解,计算机内是有很多的硬件单元,而硬件单元是要互相协同工作的。所谓的协 同,至少相互之间要能够进⾏数据传递。 但是硬件与硬件之间是互相独立的,那么如何通信呢?答案很简单,用"线"连起来。 ⽽CPU和内存之间也是有大量的数据交互的,所以,两者必须也用线连起来。通过地址总线,我们就可以了解什么是硬件编址了。

    32位机器有32根地址总线, 每根线只有两态,表示0,1【电脉冲有无】,那么⼀根线,就能表示2种含义,2根线就表示4种含义,依次类推。32根地址线,就能表示2^32种含义,每⼀种含义都代表⼀个地址。 地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。

    内存编址这件事,是靠计算机里面那些实实在在的硬件设备,按照一定的规则和办法来做好的。

    简单来说,计算机的编址是通过硬件设计把每一个内存单元的地址都固定好了,不需要把地址额外的存起来。

    知识补充:

    32位机器有32根地址总线,64位机器有64根地址总线。 地址总线是实际存在的物理电线2、指针变量和地址

    当我们了解了内存和地址的关系后,就可以开始对指针的学习啦!

    在C语言中变量创建的本质是向内存申请空间

    比如说:int a = 10;

    这串代码就相当于向内存内申请了4个字节,一个整型占4个字节,这串空间我们想存放的数据便是变量10。

    2.1 取地址操作符:&代码语言:javascript代码运行次数:0运行复制
    int main(){int a = 0x11223344;//16进制数字return 0;}

    16进制0x11223344,一个16进制位可以改写为4个二进制位,因此,11223344可以改写为32个二进制位表示,刚好一个整型可以放下。

    我们可以调试来看一下内存:

    C:初识指针—学习笔记

    打开后,输入&a 并敲下回车键,列改为一行(记得在x86环境下观察,比较方便)

    C:初识指针—学习笔记
    C:初识指针—学习笔记

    我们可以看到44,33,22,11都各占一个字节,每一个字节都有一个地址。

    我们将列数改为4列再观察

    C:初识指针—学习笔记

    从上面我们可以看到a确实向内存申请了4个空间。

    读到这我们可能会有一个新的问题,欸,4个字节都有地址,那我们怎么知道a的地址是哪一个呢?

    还记得前面调试的时候我们是怎么观察地址的吗?我们通过输入&a按下回车后出现了0x00E2FEC4,因此0x00E2FEC4便是a的地址,我们也可以发现这个地址和 44 所占字节的地址一样。

    总结一下,&a取出的是a所占4个字节中地址较小的字节的地址

    虽然整型变量占用4个字节,但是我们只要知道了第一个字节地址,顺藤摸瓜访问到4个字节的数据也是可行的。

    代码展示一下,怎么打印地址

    代码语言:javascript代码运行次数:0运行复制
    int main(){int a = 0x11223344;printf("&a=%p\n", &a);return 0;}

    知识补充:

    &是取地址操作符,想要得到地址,就需要使用这个操作符 %p:用来打印地址的占位符

    结果展示:

    C:初识指针—学习笔记

    和前面调试的结果不是一样,是因为在打印的时候又申请了新的空间。

    2.2 指针变量

    在我们之前学习的过程中,我们如果想要将一个整数存储起来,就会创建一个整型变量,比如我们想存储数字10,如下代码:

    代码语言:javascript代码运行次数:0运行复制
    int main(){int a = 10;return 0;}

    我们通过创建了一个整型变量 a 来存储10。

    那么如果我们想要将我们通过&得到的地址存储起来,有没有什么办法呢?我们可以将地址存储在指针变量中。比如我们想要存放 n 的地址

    代码语言:javascript代码运行次数:0运行复制
    int main(){int a = 10;int * pn = &n;return 0;}

    解读:int * pn = &n;

    1、pn被称为指针变量

    为什么呢?

    &n——n的地址——地址就是指针

    pn = &n;

    pn就是用来存放地址的,也可以说是用来存放指针的

    指针变量就是存放指针的变量。

    可以通过和整型变量来理解指针变量,

    整型变量:a就是用来存放整数的。

    2、int * 被称为指针类型

    int a = 10; int * pn = &n;

    对比就可以发现,int是整数的类型,int*是指针的类型。

    2.3 如何拆解指针类型

    上文说到了之指针的类型是(int *),那么我们该如何理解指针类型呢?

    pn的类型是int *,我们需要分别理解

    *:说明pn是指针变量int:说明pn指向的对象是int类型代码语言:javascript代码运行次数:0运行复制
    char ch = 'x';

    如果我们想要存放x的地址该怎么写呢?

    这样我们就存放了x的地址

    * 告诉我们pc是指针

    char则告诉我们指针指向的对象是char类型。

    2.4 解引用操作符(*)

    当我们将地址保存起来后,是为了后面能够使用,那么我们该怎么使用呢?

    在现实生活中,我们使用地址要找到⼀个房间,在房间里可以拿去或者存放物品。

    C语言中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针) 指向的对象,这里必须学习⼀个操作符叫解引用操作符(*)。

    代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 10;int * pn = &n;    //解引用操作符(间接访问操作符)*pn = 100;printf("%d", n);return 0;}

    上述代码中的*pn就使用了解引用操作符, *pn 的意思就是通过pn中存放的地址,找到指向的空间, *pn其实就是n变量了;所以*pn=100,这个操作符是把n改成了100.

    C:初识指针—学习笔记

    从结果上看,n的值的确被改为了100

    或许通过这个例子你会觉得指针有是什么用?如果只是想修改n的值,为什么不直接写一个n=100呢?这样不是更方便吗?

    其实这里是把n的修改交给了pn来操作,这样对n的修改,就多了⼀种的途径,写代码就会更加灵活, 后期慢慢就能理解了。

    其实这里有一个很好的例子能说明指针的作用,生活中,有些事情是不方便自己去做的,因此呢,就需要委托别人来代替你做,比如说一个老板想要喝奶茶,但是他不会自己顶着大太阳出去买,而是会吩咐他的秘书取帮他完成,差不多就是这样,可能有些不恰当,见谅哈!

    2.5 指针变量的大小

    我们知道我们创建一个整型变量int的大小是4个字节,字符变量char的大小是1个字节,那么指针变量的大小又是多少呢?

    思考过程:

    指针变量存放的是地址,地址的存放需要多大的空间呢?知道地址存放的空间就是指针变量的大小

    也就是说指针变量的大小取决与地址的大小

    通过前面的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后 是1或者0,那我们把32根地址线产生的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储。

    如果指针变量是用来存放地址的,那么指针变的大小就得是4个字节的空间才可以。

    同理64位机器,假设有64根地址线,⼀个地址就是64个二进制位组成的⼆进制序列,存储起来就需要 8个字节的空间,指针变量的大小就是8个字节。

    代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 10;int * pn = &n;printf("%zd\n", sizeof(pn));return 0;}

    在32位机器上: 可以看到打印的大小是4个字节

    C:初识指针—学习笔记

    在64位机器上: 可以看到打印的大小是8个字节

    C:初识指针—学习笔记

    那么指针类型是否会影响指针变量的大小呢?我们来测试一下

    代码语言:javascript代码运行次数:0运行复制
    int main(){printf("%zd\n", sizeof(int*));//整型printf("%zd\n", sizeof(char*));//字符printf("%zd\n", sizeof(short*));//短整型printf("%zd\n", sizeof(double*));//双精度浮点型return 0;}

    在32位系统上结果:

    C:初识指针—学习笔记

    在64位系统上结果

    C:初识指针—学习笔记

    我们可以看到,不管指针类型是什么,都不会影响指针变量的大小,指针类型的变量大小,在相同平台下,大小都是相同的。

    总结:

    32位平台下地址是32个bit位,指针变量大小是4个字节 64位平台下地址是64个bit位,指针变量大小是8个字节 X64环境输出结果 注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。3、指针变量类型的意义

    既然指针变量大小与指针类型无关,那么为什么还要搞指针的变量类型呢?

    3.1 指针的解引用代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 0x11223344;int* pi = &n;*pi = 0;return 0;}

    调试过程:(注意观察内存里的值)

    C:初识指针—学习笔记

    运行到292行时内存展示44 33 22 11

    C:初识指针—学习笔记

    当经过*pi = 0 之后

    内存里4个字节全部变为了 0

    如果我们不用int *的指针类型,改为char *的类型,结果又是如何呢?

    C:初识指针—学习笔记

    我们可以看到只是将n的第⼀个字节改为0。

    我们可以看到int类型指针可以访问4个字节,而char类型指针只访问了1个字节。

    通过对比,我们可以得到一个结论:

    结论:指针的类型决定了,对指针解引用的时候有多大的权限(一次能操作几个字节)。

    3.2 指针+-整数代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 0x11223344;int* pi = &n;char* pc = &n;printf("&n = %p\n", &n);printf("pi = %p\n", pi);printf("pi+1 = %p\n", pi+1);printf("pc = %p\n", pc);printf("pc+1= %p\n", pc+1);return 0;}

    结果:

    C:初识指针—学习笔记

    我们可以发现, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。 这就是指针变量的类型差异带来的变化。指针+1,其实跳过1个指针指向的元素。指针可以+1,那也可以-1。

    结论:指针的类型决定了指针向前或者向后走一步有多大(距离)。

    4、void* 指针

    void的意思是无,或者空

    所以void*指针是无具体为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引用的运算。

    代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 10;char* pc = &n;return 0;}

    在上面的代码中,将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。编译器给出了⼀个警告(如下图),是因为类型不兼容。而是用void*类型就不会有这样的问题。

    C:初识指针—学习笔记

    使用void*类型的指针接收地址就不会出现警告

    C:初识指针—学习笔记

    void* 类型的指针不能直接进行指针的+-整数和解引用的运算

    代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 10;void* pc = &n;*pc = 20;return 0;}

    当我们想运行的时候,就会报下面这个错误

    C:初识指针—学习笔记

    void* 类型的指针可以接收不同类型的地址,但是无法直接进行指针运算。

    这是因为void*是一个无具体类型的指针,当进行解运算的时候,没法确定访问几个字节。

    既然如此,那void*有什么作用呢?

    专门用来存放别人传送过来的地址,当你不知道别人给你传的是什么类型的指针的时候,就可以使用void*来存放,当需要进行解运算的时候,在使用强制类型转换来实现。

    比如:

    代码语言:javascript代码运行次数:0运行复制
    int main(){int n = 10;void* pc = &n;*(int*)pc = 20;return 0;}

    这样就将类型强制转换成了整型指针,结果就可以打印出来了

    C:初识指针—学习笔记
    结语:

    本篇文章主要讲了指针的基本知识,通过本篇文章能够了解什么是指针,指针变量,指针类型是什么。后面会继续更新指针相关知识,希望能够帮助大家攻克指针这一模块。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    硬件相关 变量
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。