1. 指针的本质与内存模型
指针作为C/C++语言中最强大也最危险的工具之一,其核心价值在于直接操作内存地址。理解指针首先要建立清晰的内存模型认知。在32位系统中,每个指针变量占用4字节内存空间,64位系统则为8字节,这与地址总线的宽度直接相关。
内存地址通常以十六进制表示,例如0x7ffee435a7dc。当我们声明int* p时,p变量存储的就是这样一个地址值。指针的类型(如int*、char*)决定了编译器如何解释该地址开始的内存内容。
关键理解:指针变量本身存储在栈或静态区,而它指向的数据可能位于任何内存区域(栈、堆、静态区)。这种分离存储特性是许多指针问题的根源。
1.1 指针的算术运算特性
指针运算遵循"类型大小感知"原则,这是区别于普通整型运算的关键特征:
c复制int arr[5] = {10,20,30,40,50};
int *p = arr; // p指向arr[0]
p++; // 移动sizeof(int)字节,指向arr[1]
对于结构体指针,运算时同样会按结构体实际大小进行位移:
c复制struct Student { char name[20]; int age; };
struct Student *sp = students_array;
sp++; // 移动sizeof(struct Student)字节
2. 多级指针与指针数组
2.1 二级指针的实用场景
二级指针(int**)常用于以下场景:
- 动态二维数组的构建
- 需要修改指针本身参数的函数调用
- 字符串数组的处理
动态分配二维数组的经典模式:
c复制int **matrix = (int**)malloc(rows * sizeof(int*));
for(int i=0; i<rows; i++) {
matrix[i] = (int*)malloc(cols * sizeof(int));
}
2.2 指针数组 vs 数组指针
这两个易混淆概念的区别在于:
- 指针数组:元素为指针的数组,如
int* arr[10] - 数组指针:指向整个数组的指针,如
int (*arr)[10]
函数指针数组的典型应用——状态机实
