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--
?
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:
- 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.