指针存储地址——那么它们为什么有类型?
Source: Dev.to
为什么指针有类型
我们常听到 “指针只是存储内存地址的变量”。
这句话在技术上是对的,但不完整。如果指针仅仅是原始地址,那么所有指针都会完全相同(通常是 4 或 8 字节)。在 C/C++ 中我们有 char*、int*、double*、struct* 等等。
如果地址只是一个数字,类型为何重要?
指针类型的作用
物理内存并不区分整数、字符或浮点数;它仅仅是一串字节。指针类型充当编译器的模板,告诉它两个关键信息:
- 宽度 – 从该地址起要读取多少字节。
- 解释方式 – 读取这些字节后,如何对待它们(例如,作为有符号整数、IEEE‑754 浮点数或 ASCII 字符)。
示例可视化
考虑从地址 0x20000000 开始的四个字节内存:
| 地址 | 值 |
|---|---|
0x20000000 | 0x01 |
0x20000001 | 0x02 |
0x20000002 | 0x03 |
0x20000003 | 0x04 |
解引用 char*
char *pc = (char *)0x20000000;
char c = *pc; // reads 1 byte
编译器恰好读取一个字节 (0x01) 并把它当作字符处理。
解引用 int*
int *pi = (int *)0x20000000;
int i = *pi; // reads 4 bytes
编译器读取接下来的四个字节并将它们组合成一个整数,在小端系统上得到 0x04030201。
地址和底层数据并未改变;唯一不同的是 解释方式。
关于内存和指针的基本真理
- 内存是一个线性地址空间,由字节大小的存储单元组成。
- 地址仅仅是一个起始点。
- 指针类型告诉编译器 如何 解释该地址处的字节。
因为内存本身没有类型的概念,指针类型变得至关重要。它向编译器提供:
- 读取或写入多少字节。
- 如何解释这些字节。
- 指针算术应如何工作。
指针算术与类型缩放
指针算术会根据所指向类型的大小进行缩放。例如:
int *p;
p = /* some address */;
p + 1; // advances 4 bytes, because sizeof(int) == 4
如果 p 是 char*,p + 1 只会前进一个字节。
理解 “指针存储地址” 只是第一步。掌握指针 类型 才能揭示软件实际如何与内存交互。