写代码时经常看到 ++ 出现在指针变量旁边,比如 p++ 或 ++p,这其实就是指针自增。它不是让指针本身的值随便加一,而是根据它所指向的数据类型,移动到下一个元素的位置。
指针自增到底动了谁?
假设你有个 int 类型的数组,每个 int 占 4 个字节。定义一个指针指向数组首元素:
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr; // p 指向 arr[0]这时候执行 p++,指针 p 不是简单地加 1,而是向后移动 4 个字节,也就是指向 arr[1]。因为 int 是 4 字节,系统知道要跳一个完整的数据单元。
不同类型,步长不一样
指针自增的“步长”取决于它的类型。比如:
- char* 指针自增,移动 1 字节
- float* 指针自增,移动 4 字节
- double* 指针自增,移动 8 字节
这个机制在遍历数组或处理内存块时特别有用。像下面这段遍历字符串的代码:
char str[] = "hello";
char *p = str;
while (*p) {
printf("%c\n", *p);
p++; // 每次移动一个字符位置
}每次 p++ 都让指针走到下一个字符,直到遇到 \0 结束。
++p 和 p++ 有区别吗?
有。虽然最终指针都会前进,但用在表达式里时机不同。
int arr[] = {1, 2, 3};
int *p = arr;
int a = *p++; // 先取 *p 的值(1),再让 p 自增
int b = *++p; // 先让 p 自增,再取值上面例子中,a 得到的是 1,b 得到的是 3(中间跳过了 2)。这种细节在调试内存访问异常时很容易被忽略,导致读错数据。
实际排错场景:为什么数组越界了?
有次同事排查一个崩溃问题,循环里写了 p++,但忘了判断边界。指针一路自增冲出了分配的内存区域,访问了非法地址,程序直接段错误。这种问题在处理网络数据包解析时尤其危险——比如从 socket 读了一段 buffer,用指针逐字节分析,没控制好自增次数,就可能踩到其他内存。
解决办法很简单:加判断。
char *p = buffer;
char *end = buffer + bufsize;
while (p < end && *p) {
// 处理字符
do_something(*p);
p++;
}这样即使数据异常,指针也不会跑飞。
指针自增不是魔法,它是 C/C++ 直接操作内存的基础能力之一。理解它怎么跳、跳多远,能少走很多弯路。