1. 指针的本质与内存寻址
指针是C语言中最强大也最危险的工具之一。理解指针的本质,需要从计算机的内存模型开始讲起。现代计算机的内存可以看作一个巨大的字节数组,每个字节都有一个唯一的地址标识。指针变量就是存储这些内存地址的特殊变量。
1.1 内存地址的物理意义
在32位系统中,内存地址是一个32位的无符号整数,理论上可以寻址4GB的内存空间(2^32字节)。64位系统则使用64位地址,可以寻址的空间大得多。当我们声明一个变量时:
c复制int a = 10;
编译器会在内存中分配4个字节(假设int为32位)的空间来存储这个整数值。&a操作就是获取这块内存区域的起始地址。
注意:取地址运算符
&只能用于左值(有明确内存位置的变量),不能用于常量或表达式。例如&10或&(a+b)都是非法的。
1.2 指针变量的内部结构
指针变量本身也需要内存存储。在32位系统中,无论指针指向什么类型的数据,指针变量本身都占用4个字节(存储地址)。64位系统中指针变量占8个字节。
c复制int *p; // 指向int的指针
char *p2; // 指向char的指针
void *p3; // 无类型指针
printf("%d,%d,%d", sizeof(p), sizeof(p2), sizeof(p3));
// 32位系统输出:4,4,4
// 64位系统输出:8,8,8
指针变量的类型信息(如int *中的int)主要服务于两个目的:
- 指针算术运算时的步长(
p+1移动的字节数) - 解引用时如何解释内存中的数据
1.3 指针的解引用机制
解引用操作符*是理解指针的关键。当执行*p时,计算机会:
- 读取指针变量p中存储的地址值
- 根据指针类型确定要读取多少字节(int通常4字节,char1字节等)
- 将这些字节解释为对应类型的数据
c复制int a = 0x12345678;
int *p1 = &a;
char *p2 = (char *)&a;
printf("%x %x", *p1, *p2);
// 大端系统可能输出:12345678 12
// 小端系统可能输出:12345678 78
这个例
