C语言指针场景下++*p++与*++p++的区别及后者报错原因
C语言指针表达式
++*p++与*++p++的差异说明 核心差异来自C语言的运算符优先级、结合性规则,以及自增运算符对操作数的左值要求,这也是前者合法、后者编译报错的根本原因。
前置规则(C语言标准规定)
先明确涉及的3类运算符的属性,优先级从高到低排序:
- 后缀自增
++:优先级最高,左结合,要求操作数必须是可修改左值,运算返回右值(操作数自增前的临时副本) - 前缀自增
++、间接寻址*:优先级比后缀自增低1级,右结合;其中前缀自增同样要求操作数是可修改左值、返回左值,间接寻址操作仅要求操作数为指针类型、返回对应类型的左值。
合法表达式++*p++的执行逻辑
按照规则从高到低、同优先级按结合性拆解:
- 最先执行后缀
p++:p是指针变量,属于可修改左值,符合后缀自增的要求;运算后p本身向后移动1个元素位,返回p自增前的指针值临时副本(右值) - 同优先级右结合,接下来执行间接寻址
*:对第一步返回的指针副本做解引用,拿到p自增前所指向的内存位置,是对应类型的可修改左值 - 最后执行前缀
++:对第二步解引用得到的左值做前缀自增,把该位置存储的值+1,返回自增后的结果,整个流程完全符合语法要求。
报错表达式*++p++的编译错误原因
按同样规则拆解,第二步直接触发语法错误:
- 最先执行后缀
p++:这一步和上述合法表达式一致,p是合法左值,完成自增后返回p自增前的指针临时副本(右值,不是可修改的左值,和1+2返回的临时计算值属性一致) - 同优先级右结合,接下来要执行前缀
++:前缀自增要求操作数必须是可修改的左值,但当前传入的是第一步返回的临时右值,不满足语法要求,编译器直接抛出错误,后续的间接寻址*根本不会被执行。
这个错误本质和写
++(3+5)报错是同一个逻辑:不能对一个临时的计算结果做自增操作,临时值没有对应的可修改内存空间,无法存放自增后的结果。
测试代码相关说明
给出的测试代码报错点为printf("%d ",*++ptr++);行,如果要实现「指针移动一位后取值,再移动一位」类逻辑,不建议堆砌复杂的连续自增表达式,拆成分步写法即可,可读性和稳定性更高,示例写法:
#include <stdio.h> int main() { int arr[]={3,9,0,4,5}; int *ptr=arr; ++ptr; printf("%d ",*ptr); ++ptr; printf("%d ",*ptr); return 0; }
连续自增搭配解引用的写法本身可读性极差,即使语法合法也极易触发未定义行为,生产环境代码不推荐使用。
内容的提问来源于stack exchange,提问作者NEHA G
相关产品推荐
相关产品推荐

