讲师中心 微信公众号
AI工具推荐 视频效率加速

深入理解指针(1)

陌芳酱_7154

陌芳酱_7154

发布时间:2025-04-25 12:46:01

|

397人浏览过

|

来源于php中文网

原创

1. 内存和地址

1.1 内存

在讨论内存和地址之前,让我们从生活中的一个例子开始:假设你住在一个有100个房间的宿舍楼里,但这些房间没有编号。如果你的朋友来找你玩,他必须逐个房间寻找,这样效率很低。然而,如果我们根据楼层和房间的位置为每个房间编号,那么朋友只要知道房间号就能快速找到你。

将这个例子应用到计算机中,情况又如何呢?我们知道,计算机的CPU(中央处理器)在处理数据时,需要从内存中读取数据,并将处理后的数据存回内存。我们购买电脑时,通常看到的内存容量是8GB、16GB或32GB等。那么,如何高效管理这些内存空间呢?

实际上,内存被划分为一个个内存单元,每个内存单元的大小为一个字节。

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

一个比特位可以存储一个二进制的位1或者0。

每个内存单元相当于一个学生宿舍,一个字节的空间内可以容纳8个比特位,就像宿舍里的八人间,每个人代表一个比特位。每个内存单元都有一个编号(相当于宿舍的门牌号),有了这个编号,CPU就可以快速找到特定的内存空间。

在生活中,我们把门牌号称为地址;在计算机中,内存单元的编号也被称为地址。在C语言中,地址被称为指针。

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

深入理解指针(1)

1.2 如何理解编址

CPU访问内存中的某个字节空间,必须知道这个字节空间在内存中的位置。由于内存中的字节数量庞大,因此需要对内存进行编址(就像给众多宿舍编号一样)。计算机中的编址并不是记录每个字节的地址,而是通过硬件设计完成的。

钢琴和吉他上并没有标注“剁、来、咪、发、唆、拉、西”这样的信息,但演奏者依然能准确找到每个琴弦的位置。这是为什么呢?因为制造商已经在乐器的硬件层面上设计好了,并且所有演奏者都知道这种约定。

首先,必须理解计算机内部有很多硬件单元,这些硬件单元需要协同工作。所谓的协同,至少需要能够进行数据传递。然而,硬件与硬件之间是独立的,那么如何通信呢?答案很简单,用“线”连接起来。

CPU和内存之间也有大量的数据交互,因此,两者也必须用线连接。不过,我们今天关注一组线,称为地址总线。硬件编址也是如此。我们可以简单理解,32位机器有32根地址总线,每根线只有两种状态,表示0或1(电脉冲的有无),一根线就能表示两种含义,两根线就能表示四种含义,依此类推。32根地址线就能表示2^32种含义,每种含义都代表一个地址。地址信息被下达给内存,内存就可以找到该地址对应的数据,并通过数据总线将数据传回CPU的寄存器。

  1. 指针变量和地址

2.1 取地址操作符(&)

理解了内存和地址的关系后,我们再回到C语言。在C语言中,创建变量实际上是在内存中申请空间。例如:

深入理解指针(1)深入理解指针(1)

如上所示的代码创建了一个整型变量a,内存中申请了4个字节用于存放整数10,每个字节都有地址,如图所示,4个字节的地址分别是:

深入理解指针(1)

那么我们如何得到a的地址呢?这里需要学习一个操作符(&)——取地址操作符。

深入理解指针(1)深入理解指针(1)

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

2.2 指针变量和解引用操作符(*)

2.2.1 指针变量

通过取地址操作符(&)得到的地址是一个数值,例如:0x006FFD70。这个数值有时也需要存储起来,以便后期使用。我们将这样的地址值存放在指针变量中。例如:

深入理解指针(1)

指针变量也是一种变量,这种变量用于存储地址,存放在指针变量中的值都被理解为地址。

2.2.2 如何拆解指针类型

这里pa左边写的是int,是在说明pa是指针变量,而前面的int是在说明pa指向的是整型(int)类型的对象。

深入理解指针(1)

如果有一个char类型的变量ch,ch的地址应该放在什么类型的指针变量中呢?

2.2.3 解引用操作符

我们将地址保存起来,未来是要使用的,那么如何使用呢?

在现实生活中,我们使用地址找到一个房间,在房间里可以取走或存放物品。

Miller CSV TSV JSON 数据处理器
Miller CSV TSV JSON 数据处理器

Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。

下载

C语言中也是如此,只要拿到了地址(指针),就可以通过地址(指针)找到指向的对象。这里必须学习一个操作符——解引用操作符(*)。

深入理解指针(1)

上面的代码中第7行就使用了解引用操作符,pa的意思是通过pa中存放的地址找到指向的空间,pa实际上就是a变量;所以*pa = 0,这个操作是将a改成了0。

如果目的是把a改成0,直接写成a = 0;不就行了,为什么还要使用指针呢?实际上,这里是将a的修改交给了pa来操作,这样对a的修改就多了一种途径,写代码会更加灵活,后期慢慢就能理解了。

2.3 指针变量的大小

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

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

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

深入理解指针(1)深入理解指针(1)

结论:

  • 在32位平台下,地址是32个bit位,指针变量大小是4个字节。
  • 在64位平台下,地址是64个bit位,指针变量大小是8个字节。
  • 注意,指针变量的大小与类型无关,只要是指针变量,在相同的平台下,大小都是相同的。
  1. 指针变量类型的意义

指针变量的大小与类型无关,只要是指针变量,在同一个平台下,大小都是一样的,为什么还要有各种各样的指针类型呢?

实际上,指针类型是有特殊意义的,我们接下来继续学习。

3.1 指针的解引用

对比以下两段代码,主要在调试时观察内存的变化。

深入理解指针(1)深入理解指针(1)

调试时我们可以看到,代码1会将n的4个字节全部改为0,但代码2只是将n的第一个字节改为0。

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

例如:char的指针解引用只能访问一个字节,而int的指针解引用可以访问四个字节。

3.2 指针+-整数

深入理解指针(1)

我们可以看出,char类型的指针变量+1跳过1个字节,而int类型的指针变量+1跳过了4个字节。这就是指针变量的类型差异带来的变化。指针+1实际上是跳过一个指针指向的元素。指针可以+1,也可以-1。

结论:指针的类型决定了指针向前或向后移动一步的距离。

3.3 void* 指针

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

深入理解指针(1)

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

深入理解指针(1)

使用void*类型的指针接收地址:

深入理解指针(1)

VS编译代码的结果:

深入理解指针(1)

这里我们可以看到,void*类型的指针可以接收不同类型的地址,但无法直接进行指针运算。

那么void*类型的指针有什么用呢?

一般void*类型的指针用于函数参数部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得一个函数可以处理多种类型的数据,在《深入理解指针(4)》中我们会详细讲解。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6799

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3265

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4248

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2905

2025.08.29

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

371

2025.11.27

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

379

2026.04.23

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

391

2026.03.13

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
计算机系统从应用层到底层
计算机系统从应用层到底层

共6课时 | 0.6万人学习

开源物联网开发实例
开源物联网开发实例

共6课时 | 0.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn