深入理解 C++ 中的指针与自增表达式:*a++、(*a)++ 和 *++a 的区别解析
一、运算符优先级与结合性
首先,运算符优先级决定了表达式的解析方式:
后缀自增
a++的优先级高于解引用*前缀自增
++a的优先级也高于解引用*括号
()拥有最高优先级,可以改变默认运算顺序
基于此:
*a++等价于*(a++)(*a)++等价于 对*a的值做后缀自增*++a等价于*(++a)
二、逐个拆解分析
2.1 *a++ —— 指针先用后自增
含义:
指针
a当前指向一个地址解引用
*a得到该地址的值后缀自增
a++先使用当前指针值,然后指针向后移动一格
执行顺序:
取
a当前值(指向arr[0])解引用得到
arr[0]的值:10a自增,指向arr[1]
代码示例:
int arr[] = {10, 20, 30};
int* a = arr; // 指针 a 指向数组首元素 arr[0]std::cout << *a++ << std::endl; // 输出 10
std::cout << *a << std::endl; // 输出 20,说明 a 指向下一个元素了
2.2 (*a)++ —— 值先用后自增,指针不变
含义:
*a访问当前指针指向的值对该值进行后缀自增(值加一)
指针本身不发生变化
执行顺序:
取
*a当前值(例如20)输出该值
将该值加一存回内存(即
arr[1]变成21)
代码示例:
int arr[] = {10, 20, 30};
int* a = arr; // 指针 a 指向数组首元素 arr[0]std::cout << (*a)++ << std::endl; // 输出 10
std::cout << *a << std::endl; // 输出 11,值被修改了
2.3 *++a —— 指针先自增再解引用
含义:
前缀自增:指针
a先向后移动一格解引用新位置的值
执行顺序:
指针
a自增,指向arr[2]解引用
*a,得到30
代码示例:
int arr[] = {10, 20, 30};
int* a = arr; // 指针 a 指向数组首元素 arr[0]std::cout << *++a << std::endl; // 输出 20
std::cout << *a << std::endl; // a 现在指向 arr[2]
三、总结和源码
| 表达式 | 含义 | 指针移动 | 访问的值 | 值是否变化 |
|---|---|---|---|---|
*a++ | 先取当前指针指向的值,再指针后移 | 指针后移 | 当前指针指向的值 | 否 |
(*a)++ | 当前指针指向的值后缀自增 | 指针不变 | 当前指针指向的值 | 是,值 +1 |
*++a | 指针先前缀自增,再取新地址值 | 指针前移 | 新指针指向的值 | 否 |
完整示例代码
注意!连续执行和分开执行如果不重置指针指向结果也会不一样,上文是分开执行的,下面是连续执行的结果:
#include <iostream>int main() {int arr[] = {10, 20, 30};int* a = arr;std::cout << "*a++: " << *a++ << std::endl; // 输出 10,a 指向 arr[1]std::cout << "*a after *a++: " << *a << std::endl; // 输出 20std::cout << "(*a)++: " << (*a)++ << std::endl; // 输出 20,arr[1] 变成 21std::cout << "*a after (*a)++: " << *a << std::endl; // 输出 21std::cout << "*++a: " << *++a << std::endl; // a 指向 arr[2],输出 30std::cout << "*a after *++a: " << *a << std::endl; // 输出 30return 0;
}
