
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、游戏、规划
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录
-
- 一、先搞透:内存和地址是啥?💾
- [二、指针变量:存地址的专属容器 📦](#二、指针变量:存地址的专属容器 📦)
-
- [1. 取地址操作符 `&`:把地址揪出来](#1. 取地址操作符
&:把地址揪出来) - [2. 定义指针变量:专门存地址的变量](#2. 定义指针变量:专门存地址的变量)
- [3. 解引用操作符 `*`:通过地址操作变量 🔍](#3. 解引用操作符
*:通过地址操作变量 🔍)
- [1. 取地址操作符 `&`:把地址揪出来](#1. 取地址操作符
- [三、指针变量的小秘密:类型和大小 🤫](#三、指针变量的小秘密:类型和大小 🤫)
-
- [1. 指针变量的大小:只和系统有关!](#1. 指针变量的大小:只和系统有关!)
- [2. 指针类型的意义:决定操作范围 📏](#2. 指针类型的意义:决定操作范围 📏)
-
- [① 解引用时操作多少字节](#① 解引用时操作多少字节)
- [② 指针移动时跳多少步](#② 指针移动时跳多少步)
- [3. `void*`指针:万能的地址垃圾桶 🗑️](#3.
void*指针:万能的地址垃圾桶 🗑️)
- [四、指针运算:让指针动起来 ⚡](#四、指针运算:让指针动起来 ⚡)
-
- [1. 指针 ± 整数:遍历数组超方便](#1. 指针 ± 整数:遍历数组超方便)
- [2. 指针 - 指针:算元素个数](#2. 指针 - 指针:算元素个数)
- [3. 指针的关系运算:比较地址大小](#3. 指针的关系运算:比较地址大小)
- [写在最后 📝](#写在最后 📝)
✨指针是C语言的灵魂,也是学好底层编程的关键~ 这篇会从内存底层 讲到指针实战,保证你看完能从懵变懂!
一、先搞透:内存和地址是啥?💾
要学指针,得先明白内存是怎么干活的------
内存是电脑的临时仓库🏠,程序运行时的所有数据(变量、数组、函数等)都存在这里。
它被切成了很多1字节大小的小格子(内存单元),每个格子能存8个二进制位(bit),相当于一个8位的小抽屉🧩。
为了能快速找到这些抽屉,系统给每个内存单元分配了一个唯一编号 ------这就是地址 ,也叫指针!(划重点:地址 = 指针 ✍️)
举个例子:内存像一排带编号的储物柜,每个柜子对应一个内存单元,柜子的编号就是地址。你报编号(地址),就能精准找到对应的柜子(内存单元)~
二、指针变量:存地址的专属容器 📦
知道了地址是啥,那怎么在代码里用它?这就需要指针变量!
1. 取地址操作符 &:把地址揪出来
想拿到变量的地址,用&就行~ 比如定义一个int a = 10:
c
#include <stdio.h>
int main() {
int a = 10; // 向内存申请4个连续字节,存数值10
// 用&a取a的地址,%p是打印地址的格式符
printf("a的地址:%p\n", &a);
return 0;
}
注意⚠️:
int类型占4字节,但&a拿到的是这4个字节里最小的那个字节的地址(也就是起始地址)~
2. 定义指针变量:专门存地址的变量
地址得找个容器存起来,这个容器就是指针变量 !定义格式是类型* 变量名:
类型:表示指针指向的变量的类型 (比如int*就是指向int变量的指针);*:表示这个变量是指针变量。
示例:
c
#include <stdio.h>
int main() {
int a = 10;
// 定义int类型的指针变量pa,存a的地址
int* pa = &a;
return 0;
}
可以理解为:pa是个地址标签🏷️,贴在了a的内存单元上,通过pa就能找到a~
3. 解引用操作符 *:通过地址操作变量 🔍
存地址不是目的,目的是通过地址操作变量的值 !这就要用*(解引用):
c
#include <stdio.h>
int main() {
int a = 10;
int* pa = &a;
// *pa 表示pa指向的变量,这里就是a,输出10
printf("通过pa访问a:%d\n", *pa);
*pa = 20; // 通过pa修改a的值
printf("修改后的a:%d\n", a); // 输出20
return 0;
}
简单说:*是通过地址找变量的钥匙🔑,用*指针变量就能直接读写目标变量~
三、指针变量的小秘密:类型和大小 🤫
1. 指针变量的大小:只和系统有关!
不管指针指向啥类型,它的大小只由系统的位数决定:
- 32位系统:地址是32个bit → 占4字节;
- 64位系统:地址是64个bit → 占8字节。
看代码验证(64位系统下):
c
#include <stdio.h>
int main() {
int* pa; // 指向int的指针
char* pc; // 指向char的指针
// 输出都是8(64位系统)
printf("int*的大小:%zd\n", sizeof(pa));
printf("char*的大小:%zd\n", sizeof(pc));
return 0;
}
2. 指针类型的意义:决定操作范围 📏
指针的类型不是摆设!它决定了两件事:
① 解引用时操作多少字节
比如int*和char*指向同一个int变量:
c
#include <stdio.h>
int main() {
// a占4字节,内存中是0x11 0x22 0x33 0x44
int a = 0x11223344;
int* pa = &a;
char* pc = &a;
*pa = 0; // int*解引用:操作4字节 → a变成0x00000000
// *pc = 0; // char*解引用:只操作1字节 → a变成0x11223300
return 0;
}
② 指针移动时跳多少步
指针±整数时,偏移量由指针类型决定:
c
#include <stdio.h>
int main() {
int a = 10;
int* pa = &a;
char* pc = &a;
printf("pa+1的地址:%p\n", pa + 1); // int*跳4字节
printf("pc+1的地址:%p\n", pc + 1); // char*跳1字节
return 0;
}
总结:指针类型决定了操作的粒度,不能随便混用~
3. void*指针:万能的地址垃圾桶 🗑️
void*是无类型指针,可以存任意类型变量的地址 ,但有个缺点:不能直接解引用/做运算,得先强制类型转换:
c
#include <stdio.h>
int main() {
int a = 10;
void* pv = &a; // 存int的地址
// *pv = 20; // 直接用会报错!
*(int*)pv = 20; // 强制转成int*,就能正常用啦
return 0;
}
void*常用在函数参数里(比如实现泛型),后面会详细讲~
四、指针运算:让指针动起来 ⚡
指针不是死地址,它能做运算!常用的有3种:
1. 指针 ± 整数:遍历数组超方便
数组在内存中是连续存储的,用指针±整数可以直接遍历元素:
c
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int* p = &arr[0]; // 指向数组第一个元素
for (int i = 0; i < 5; i++) {
// p+i 指向第i个元素,*(p+i)就是元素值
printf("%d ", *(p + i));
}
return 0; // 输出:1 2 3 4 5
}
也能反向遍历(从最后一个元素开始):
c
int* p = &arr[4]; // 指向最后一个元素
for (int i = 0; i < 5; i++) {
printf("%d ", *(p - i)); // 输出:5 4 3 2 1
}
2. 指针 - 指针:算元素个数
前提:两个指针必须指向同一块连续内存(比如同一个数组),结果是两个指针之间的元素个数:
c
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
// 输出4(下标4和下标0之间的元素个数)
printf("元素个数:%d\n", &arr[4] - &arr[0]);
return 0;
}
经典用法:模拟实现strlen(统计字符串长度):
c
#include <stdio.h>
// 自己写的strlen
size_t my_strlen(char* p) {
char* q = p;
while (*q != '\0') { // 找到字符串结束符'\0'
q++;
}
return q - p; // 指针差=字符个数
}
int main() {
char str[] = "hello";
printf("字符串长度:%zd\n", my_strlen(str)); // 输出5
return 0;
}
3. 指针的关系运算:比较地址大小
指针可以用>、<、>=、<=比较地址,常用在遍历连续内存:
c
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int* p = &arr[0];
// 当p没超过数组末尾地址时,继续循环
while (p < &arr[5]) {
printf("%d ", *p);
p++;
}
return 0; // 输出:1 2 3 4 5
}
写在最后 📝
指针其实没那么难,核心逻辑就3句话:
- 地址就是指针,是内存单元的唯一编号;
- 指针变量是存地址的容器,用来间接操作目标变量;
- 解引用和指针运算,是指针实现高效操作的关键。
多写代码+调试(比如打印地址、观察指针移动),很快就能摸清指针的脾气~ 下一篇会讲继续讲解呀,记得来看哦🥰!