Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator precedence is confusing in this case

Lets say I have a struct

struct s
{
    int a;
}

and a main function like this

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;
}

Output :

9
9

As per operator precedence, -> and -- have same precedence and left->right associativity.

In case of sptr->a--, I can understand sptr->a was done first and then -- was applied.

But in case of --sptr->a, -- should be applied to sptr first. This may lead to undefined behaviour but it should be the case. Why does this still work same as sptr->a-- ?

like image 978
mhsquare Avatar asked Oct 18 '25 01:10

mhsquare


2 Answers

It is only postfix increment/decrement which has the same precedence as ->. Prefix increment/decrement has lower precedence.

Thus in the case

   sptr->a--;

-- is applied last due to left-to-right associativity.

In the case

   --sptr->a;

-- is applied last due to -> having higher precedence.

Update (since the "language-lawyer" tag was added to the question):

The normative part of the C Standard (note that references below are to C23 draft N3220 which may differ from the finalized version) defines operator precedence and associativity rather implicitly by the language syntax grammar.

Clause 6.5.1-3 reads:

The grouping of operators and operands is indicated by the syntax.82) Except as specified later, side effects and value computations of subexpressions are unsequenced.83)

And note 82 reads:

  1. The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first. [...]
    Within each major subclause, the operators have the same precedence. Left- or right-associativity is indicated in each subclause by the syntax for the expressions discussed therein.

"Postfix operators" (such as -> and postfix --) are found in section 6.5.3 and "Unary operators" (such as prefix --) are found in section 6.5.4. This establishes the order of precedence (which by the way also is implied by the grammar excerpts in clauses 6.5.3.1-1 and 6.5.4-1).

To determine associativity, the syntax for Postfix operators (6.5.3.1-1) is as follows:

postfix-expression:   
       primary-expression   
       postfix-expression [ expression ]   
       postfix-expression ( argument-expression-listopt )   
       postfix-expression . identifier   
       postfix-expression -> identifier   
       postfix-expression ++   
       postfix-expression --   
       compound-literal

Which implies that, for example, the expression sptr->a-- is interpreted as (sptr->a) --.
I.e. -- is preceded by the postfix-expression sptr->a. Thus the associativity is left-to-right.

For a complete table of operator precedence and associativity (though based on C11), see here.

like image 82
nielsen Avatar answered Oct 20 '25 19:10

nielsen


As per operator precedence, -> and -- have same precedence and left->right associativity.

-> and postfix -- have the same precedence and left-to-right associativity, so sptr->a-- is (sptr->a)--.

-> and prefix -- don't have the same precedence, -- is lower. Thus --sptr->a is --(sptr->a).

like image 22
Abstraction Avatar answered Oct 20 '25 18:10

Abstraction



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!