You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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--一致,这是为什么?


解答

这里的核心是要理清前缀--、后缀--与->的优先级和结合性细节:

  1. 优先级差异:后缀--的优先级实际上高于->,所以sptr->a--会被解析为(sptr->a)--,也就是先访问成员a,再对其做后缀递减,这和你的理解一致。
  2. 前缀--的左结合性正确应用:前缀--和->优先级相同,遵循左结合性,但左结合性的作用是确定相同优先级运算符的分组顺序,而非直接对最左侧的变量应用运算符。对于--sptr->a,左结合性要求我们先处理左侧的运算单元:sptr->a是一个完整的指针成员访问表达式,所以整个表达式会被分组为--(sptr->a),也就是先通过sptr访问成员a,再对a的值做前缀递减。
  3. 错误理解的根源:你误以为左结合性是让--直接作用于sptr,但实际上结合性是针对运算符的组合方式。只有当表达式写成(--sptr)->a时,才会先对指针sptr本身做递减,这才会导致指针指向非法内存,产生未定义行为——而你的代码里并没有这种写法。

综上,不管是sptr->a--还是--sptr->a,最终都是对s1.a进行递减操作,所以输出结果一致。

内容的提问来源于stack exchange,提问作者mhsquare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:42:43