
🍀指尖燃热血,代码铸锋芒;以信仰破局,向顶峰生长
🎬秦苒&的简介:

前言:今天这篇文章,我会把指针的核心模块(对应目录里的内存基础、指针变量、类型意义、const修饰、指针运算)拆解开,从"是什么""为什么""怎么用"三个维度做系统化梳理:小到指针变量的大小,大到指针减指针的本质,尽量用直白的逻辑+案例帮你把这些知识点串成一张清晰的网。
不管你是刚接触指针的新手,还是想补全知识漏洞的进阶学习者,跟着这篇梳理走,应该能让"指针"从"抽象概念"变成你代码里顺手的工具~
ps:由于篇幅有限,关于指针的学习我会分成多篇文章介绍。
文章目录
- 一、内存和地址
- 二、指针变量和地址
- [三、 指针变量类型的意义](#三、 指针变量类型的意义)
- [四、const 修饰指针](#四、const 修饰指针)
-
- [4.1 const修饰变量](#4.1 const修饰变量)
- [4.2 const修饰指针变量](#4.2 const修饰指针变量)
- 五、指针的运算
-
- [5.1 指针+-整数](#5.1 指针+-整数)
- 5.2指针-指针
- 5.3指针的关系运算
- 总结
- 结尾
提示:以下是本篇文章正文内容,下面案例可供参考
一、内存和地址
1.1内存
计算机中的内存地址,本质就是内存空间的"门牌号" ------内存是由无数个"存储单元"(类似小抽屉)组成的,每个单元能存1字节(8位)数据
内存地址就是给每个"小抽屉"分配的唯一编号,让CPU能快速找到并读写对应的数据。
像这样:

核心类比(一看就懂):把内存想象成一栋巨大的"数据公寓",每一间房就是一个存储单元(存1字节数据),内存地址就是每间房的门牌号(比如1001、1002...)。CPU要读取/写入数据时,只要知道对应的"门牌号"(地址),就能直接找到目标房间,不用挨个翻找,极大提升效率。
在计算机中,也是如此!
在计算机中,我们把内存单元的编号称为内存地址,而C语言中的地址叫指针。
因此我们理解为:
内存单元的编号== 地址 ==指针
这里我补充一下计算机中常见单元如下:
1Byte=8bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
1.2编址
什么是编址?
"编址"(内存编址),就是给计算机内存的每一个存储单元,分配一个唯一的编号(也就是咱们刚说的内存地址)的过程------本质是"给内存的'小抽屉'编门牌号",让CPU能通过编号精准找到对应单元,是内存和CPU通信的基础。
为什么要编址?
解决"CPU找不到数据"的问题。如果不编址,内存里的几十亿个存储单元就是"乱堆的抽屉",CPU要找一个数据得挨个翻,速度慢到无法使用;编址后,每个单元有唯一地址,CPU直接"按号找房",效率拉满。
怎么样编址?
编址是"分配地址"的过程,分配完之后,每个变量(比如 int a=10 )在内存中占用的单元,就有了自己的地址( &a );而指针( int *p ),就是用来存这个"编好的地址"的变量------相当于"你先给房间编好门牌号(编址),再把门牌号写在纸条上(指针p),CPU拿着纸条就能找到房间(变量a)
我们结合图片理解一下:

而上图中的CPU和内存属于硬件,硬件和硬件之间是相互独立的。为了让硬件间相互通信,我们用"线"将他们连起来。
今天我们先了解"地址总线"。
我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表示0,1【电脉冲有无】,那么⼀根线,就能表示2种含义,2根线就能表示4种含义,依次类推。32根地址线,就能表示2^32种含义,每⼀种含义都代表⼀个地址。地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。
二、指针变量和地址
2.1取地址操作符(&)
题外话:话说我名字(秦苒&)就有这个符号,这可不是随便取的名字,等指针这一板块知识点全部整理完,我给大家解释一下吧!
进入正题!!
在C语言中创建变量就是在向内存申请空间。比如说:

上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都有地址,上图中4个字节的地址分别是:
0x006FFD70
0x006FFD71
0x006FFD72
0x006FFD73
怎么样得到a的地址呢?
我们就需要引入&---取地址操作符
总结:
指针---地址
指针变量---存放地址的变量
c
#include<stdio.h>
int main()
{
int a = 0;
&a;//取出a的地址
printf("%d\n",&a);
return 0;
}
&a取出的是a所占4个字节中地址较小的字节的地址

则 打印结果为:006FFD70
虽然整型变量占用4个字节,我们只要知道了第⼀个字节地址,访问到4个字节的数据也是可行的。
2.2指针变量和解引用操作符(*)
我们通过取地址操作符(&)拿到的地址是⼀个数值,比如:0x006FFD70,这个数值有时候也是需要
存储起来,方便后期再使用的,那我们把这样的地址值存放在哪里呢?答案是:指针变量中。
如
c
#include <stdio.h>
int main()
{
int a = 10;
int * pa = &a;//取出a的地址并存储到指针变量pa中
return 0;
}
指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
上述代码中:
int*是pa的类型,*是在说明pa是指针变量,而前面的int 是在说明pa指向的是整型(int)类型的对象
- 如何使用地址?
我们只要拿到了地址(指针),就可以通过地址(指针)找到地址针指向的对象,这里必须学习⼀个操作符叫解引用操作符(*)。

- *pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量了;所以 *pa=0,这个操作符是把a改成了0.
2.3指针变量的大小
如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以。
即64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节的空间,指针变量的大小就是8个字节。
c
#include <stdio.h>
//指针变量的⼤⼩取决于地址的⼤⼩
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%zd\n", sizeof(char *));
printf("%zd\n", sizeof(short *));
printf("%zd\n", sizeof(int *));
printf("%zd\n", sizeof(double *));
return 0;
}
输出结果为:

于是我们得到以下结论
·32位平台下地址是32个bit位,指针变量大小是4个字节
·64位平台下地址是64个bit位,指针变量大小是8个字节
·注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的
三、 指针变量类型的意义
指针变量的大小和类型无关,只要是指针变量,在同⼀个平台下,大小都是⼀样的。为什么还要有各种各样的指针类型呢?其实指针类型是有特殊意义的!大家接着看,听我为大家分析!
3.1指针的解引用

通过观察,我们不难发现:char* 的指针解引用就只能访问一个字节,而int* 的指针的解引用就能访问四个字节
即为:指针的类型决定了,对指针解引用的时候有多大的权限(⼀次能操作几个字节)
3.2指针±整数
大家注意观察指针的变化:
c
#include <stdio.h>
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("&n=%p\n", &n);
printf("pc=%p\n", pc);
printf("pc+1=%p\n", pc + 1);
printf("pi=%p\n", pi);
printf("pi+1=%p\n", pi + 1);
return 0;
}
运行结果如下:

通过观察我们发现:
·指针变量的大小和类型无关
·char* 类型的指针变量+1跳过1个字节,int* 类型的指针变量+1跳过了4个字节。这就是指针变量的类型差异带来的变化。指针+1,其实跳过1个指针指向的元素。指针可以+1,那也可以-1
结论:
指针变量的类型决定指针前进或后退的距离(可以一次跳过几个字节)
3.3 void* 指针
void* 可以理解为⽆具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址。
c
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
char* pc = &a;
return 0;
}
因为我们将int型的变量的地址赋给了char*型的指针变量,因此编译器出现报错:

在这时,就体现了void* 类型的指针的作用。只要我们把int* 改为void*,程序便可以正常运行啦!
但是需要注意的是无法直接进行指针运算

但是如果我们给出啦指针的类型,程序正常运行结果如下:

总结:⼀般void* 类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得⼀个函数来处理多种类型的数据,在后面的博客我会详细解说。
四、const 修饰指针
4.1 const修饰变量

去掉第五行(n=20;)的运行结果:

4.2 const修饰指针变量
const修饰指针变量,可以放在 * 的左边,也可以放在 * 的右边,意义是不⼀样的。
• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本⾝的内容可变。
• const如果放在 * 的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变
五、指针的运算
指针的基本运算有三种
• 指针±整数
• 指针-指针
• 指针的关系运算
接下来听我逐一介绍:
5.1 指针±整数
前提:同类型且指向同一个连续内存块(比如同一数组),否则结果是未定义的
只有 char* 的指针相减(因为 char 占1字节)结果才等于"字节数"。

5.2指针-指针

5.3指针的关系运算

总结
C语言指针的核心,其实是"通过地址操控内存"------从内存编址的底层逻辑,到指针变量的"存地址、解引用",再到类型、const、运算这些规则,本质都是围绕"如何安全、高效地操作内存"展开的。
如果你看完这篇还觉得晕,不妨记住这3个"锚点":
· 指针变量存的是地址, & 是"拿地址", * 是"用地址里的内容";
·指针类型决定操作范围: char* 动1字节、 int* 动4字节,运算结果是"元素个数"而非字节数;
· 规则是"保护盾":const限定操作权限,指针运算只在同一块连续内存里合法,踩线就会出bug。
把这些锚点和实际代码结合(比如用指针遍历数组、传址修改变量),指针很快就能从"抽象概念"变成你写代码的"顺手工具"。
结尾
勇敢的寻宝者啊,这次旅途你挖掘到多少宝藏呢,苒苒很期待下次与您相遇!
结语:希望对寻找C语言相关内容的寻宝者有所帮助,不要忘记给博主"一键三连"哦!你的每一次鼓励都为我提供 了前行的动力!
小喵很期待与你再次寻宝奥 ᰔᩚ/•᷅•᷄\୭
