为何sptr->a--与--sptr->a输出结果相同?运算符优先级疑问
关于C语言中
->与--运算符结合性的疑问 示例代码
结构体定义:
struct s { int a; };
主函数代码:
int main() { struct s s1 = {.a = 10}; struct s *sptr = &s1; sptr->a--; printf("%d\n", sptr->a); s1.a = 10; --sptr->a; printf("%d\n", sptr->a); return 0; }
程序输出:
9 9
疑问点
根据运算符优先级规则,->和--优先级相同,且遵循左结合性。对于sptr->a--,我理解是先执行sptr->a再应用--,这没问题。但对于--sptr->a,按左结合性我认为应该先对sptr应用--,这可能导致未定义行为,但实际结果却和sptr->a--一致,这是为什么?
解答
这里的核心是要理清前缀--、后缀--与->的优先级和结合性细节:
- 优先级差异:后缀
--的优先级实际上高于->,所以sptr->a--会被解析为(sptr->a)--,也就是先访问成员a,再对其做后缀递减,这和你的理解一致。 - 前缀
--的左结合性正确应用:前缀--和->优先级相同,遵循左结合性,但左结合性的作用是确定相同优先级运算符的分组顺序,而非直接对最左侧的变量应用运算符。对于--sptr->a,左结合性要求我们先处理左侧的运算单元:sptr->a是一个完整的指针成员访问表达式,所以整个表达式会被分组为--(sptr->a),也就是先通过sptr访问成员a,再对a的值做前缀递减。 - 错误理解的根源:你误以为左结合性是让
--直接作用于sptr,但实际上结合性是针对运算符的组合方式。只有当表达式写成(--sptr)->a时,才会先对指针sptr本身做递减,这才会导致指针指向非法内存,产生未定义行为——而你的代码里并没有这种写法。
综上,不管是sptr->a--还是--sptr->a,最终都是对s1.a进行递减操作,所以输出结果一致。
内容的提问来源于stack exchange,提问作者mhsquare
相关产品推荐
相关产品推荐

