why does *ptr++ act like *(ptr++) and not (*ptr)++? [duplicate] - c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
++ on a dereferenced pointer in C?
Similarly, what would
*ptr += 1
*ptr % 8, and
*ptr / 8
be?
The differences seem confusing.
Is this, perhaps, compiler dependent?

It has to do with operator precedence. The * operator has a lower precedence than ++ so it occurs last.
Here's a Wikipedia chart that lists all the operators: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
You can see in the chart that postfix ++ has a precedence of 2 while * dereference has a precedence of 3. (The numbers are slightly backwards, as lower numbers have higher precedence).

Operator precedence. The ++ operator "binds more tightly" than the * operator.
Here's the table, in order of precedence.
http://isthe.com/chongo/tech/comp/c/c-precedence.html
This is not compiler dependent. It will always behave this way.

Because of precedence (that's just how C works).
C FAQ on the * exact * subject
The postfix ++ and -- operators
essentially have higher precedence
than the prefix unary operators.
Therefore, *p++ is equivalent to
*(p++);

because of operator precedence
the postfix ++ has a higher precedence than the * operator. It's not compiler dependent.
*ptr += 1 will increase the value pointed to by ptr by one (or call the appropriate overloaded operator)
*ptr % 8 will calculate the remainder of the value pointed to by ptr divided by 8
*ptr / 8 will calculate the division of the value pointed to by ptr and 8

From wikipedia:
For the ISO C 1999 standard, section 6.5.6 note 71 states that the C grammar provided by the specification defines the precedence of the C operators
This means that the operator precedence is governed by C standard.

The differences seem confusing. Is this, perhaps, compiler dependent?
No, the precedence of operators is defined in the c lang spec.
And and so *prt++ is always deferencing the pointer before the post-increment occurs.

Related

Postfix/Prefix operator precedence and associativity

I'm confused about the precedence and associativity of postfix/prefix operators.
On one hand, as I'm reading K&R book, it states that:
(*ip)++
The parentheses are necessary in this last example; without them, the expression would increment ip instead of what it points to, because unary operators like * and ++ associate right to left.
No mention whatsoever of a difference of associativity between postfix/prefix operators. Both are treated equally. The book also states that * and ++ have the same precedence.
On the other hand, this page states that:
1) Precedence of prefix ++ and * is same. Associativity of both is right to left.
2) Precedence of postfix ++ is higher than both * and prefix ++. Associativity of postfix ++ is left to right.
Which one should I trust? Is it something that changed with the C revisions over the years?
TL;DR: the two descriptions are saying the same thing, using the same words and symbols with slightly different meaning.
On one hand, as I'm reading K&R book, it states that:
(*ip)++
The parentheses are necessary in this last example; without them, the expression would increment ip instead of what it points to,
because unary operators like * and ++ associate right to left.
No mention whatsoever of a difference of associativity between
postfix/prefix operators. Both are treated equally. The book also
states that * and ++ have the same precedence.
It's unclear which edition of K&R you're reading, but the first, at least, does treat the prefix and postfix versions of the increment and decrement operators as a single operator each, with effects depending on whether their operand precedes or follows them.
On the other hand, this page states that:
1) Precedence of prefix ++ and * is same. Associativity of both is
right to left.
2) Precedence of postfix ++ is higher than both * and prefix ++.
Associativity of postfix ++ is left to right.
The language standard and most modern treatments describe the prefix and postfix versions as different operators, disambiguated by their position relative to their operand. The rest of this answer explains how this is an alternative description of the same thing.
Observe that when only unary operators are involved, associativity questions arise only between one prefix and one postfix operator of the same precedence. Among a chain of only prefix or only postfix operations, there is no ambiguity with respect to how they associate. For example, given - - x, you cannot meaningfully group it as (- -) x. The only alternative is - (- x).
Next, observe that all the highest-precedence operators are postfix unary operators, and that in K&R, all the second-precedence operators are prefix unary operators except ambi-fix ++ and --. Applying right-to-left associativity to the second-precedence operators, then, disambiguates only expressions involving postfix ++ or -- and a prefix unary operator, and does so in favor of the postfix operator. This is equivalent to the modern approach of distinguishing the postfix and prefix versions of those operators and assigning higher precedence to the postfix versions.
To get the rest of the way to the modern description, consider the observations I already made that associativity questions arise for unary operators only when prefix and postfix operators are chained, and that all the highest-precedence operators are postfix unary operators. Having distinguished postfix ++ and -- as separate, higher-precedence operators than their prefix versions, one could put them in their own tier between the other postfix operators and all the prefix operators, but putting them instead in the same tier with all the other postfix operators changes nothing about how any expression is interpreted, and is simpler. That's how it is usually represented these days, including in your second resource.
As for left-to-right vs. right-to-left associativity, the question is, again, moot for a precedence tier containing only prefix or only postfix operators. However, describing postfix operators as associating left-to-right and prefix operators as associating right-to-left is consistent with their semantic order of operations.
You can refer to the C11 standard although its section on precedence is a little hard to follow. See sec. 6.5.1. (footnote 85 says "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.")
Basically, postfix operators are higher precedence than prefix because they come earlier in that section, 6.5.2.4 vs. 6.5.3.1. So K&R is correct (no surprise there!) that *ip++ means *(ip++), which is different from (*ip)++, however its point about it being due to associativity is a bit misleading I'd say. And the geeksforgeeks site's point #2 is also correct.
#GaryO's answer is spot on! Postfix has higher precedence because they come earlier.
Here's a small test to sanity check to convince yourself.
I made two integer arrays and a pointer to the start of each array, then ran (*p)++ and *p++ on the two pointers. I printed out the pointer and array state before and after for reference.
#include <stdio.h>
#define PRINT_ARRS printf("a = {%d, %d, %d}\n", a[0], a[1], a[2]); \
printf("b = {%d, %d, %d}\n\n", b[0], b[1], b[2]);
#define PRINT_PTRS printf("*p1 = a[%ld] = %d\n", p1 - a, *p1); \
printf("*p2 = b[%ld] = %d\n\n", p2 - b, *p2);
int main()
{
int a[3] = {1 , 1, 1};
int b[3] = {10,10, 10};
int *p1 = a;
int *p2 = b;
PRINT_ARRS
PRINT_PTRS
printf("(*p1)++: %d\n", (*p1)++);
printf("*p1++ : %d\n\n", *p2++);
PRINT_ARRS
PRINT_PTRS
}
Compiling with gcc and running on my machine produces:
a = {1, 1, 1}
b = {10, 10, 10}
*p1 = a[0] = 1
*p2 = b[0] = 10
(*p1)++: 1
*p2++ : 10
a = {2, 1, 1}
b = {10, 10, 10}
*p1 = a[0] = 2
*p2 = b[1] = 10
You can see that (*p1)++ increments the array value while *p2++ increments the pointer.

If left to right and right to left - both associativity of operator are present in a statement then What will be considered? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
int i=-1;
int a=65;
int b=a*i + ++i;
What is the value of b?
Here associativity of =,+ is left to right and associativity of *,prefix increment (++) is right to left.
So What order of evaluation should I consider for int b=a*i + ++i;
left to right?
right to left?
Why?
Do not think about assosiativity. Think about order of evaluation and unfortunately it is undefined in this case.
In the expression
int b=a*i + ++i;
you are modifying i as well as using it in the same expression which invokes undefined behavior.
C99 states that:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.
Further I would suggest you to read c-faq: Q 3.8.
here you should consider the operator precedence. here the expression is solved based on precedence of the operator so at a time only one associativity is applied.
The associativity comes into picture when the operator has same precedence and in that case associativity will be same.
In your question b=a*i + ++i i used twice results in undefined behavoiur.
otherwise it would be evaluated as,
++ followed by * then + operation according to precedence.
if this was followed the the answer would be,
b=a*i + ++i
b=65*i + 0
b=65*0 + 0
b=0 + 0
b=0
but the compiler can use the stored value of i instead of using value after ++i,
b=a*i + ++i
b=a*-1 + 0
b=-65 + 0
b=-65
this results in undefined behaviour since b can be 0 or -65. and also you can see that associativity doesn't create problem while evaluating since operators with same precedence will have same associativity and evaluation is ordered by precedence first and within that ordered by associativity.
There are two things associativity and precedence .
First check precedence and then associativity.
In you expression int b=a*i + ++i;
++has higher precedence than + and * so first ++ would be evaluated.
After that + and *, * has higher precedence so * is evluated.
In the last + is evaluated.
It's also the case as haccks suggested, you should not modify and use the value in the same expression.(not a good practice)

Issue with precedence and ++ and * unary operators in C

My question is not long, but it's puzzling for me. I'm one of those people who (and I think rightfully so) want to know every single rule of the languages they learn. I want to know why the language does what it does.
So, why does ++*i increment the value of *i, rather than the i pointer? The preincrement operator has a higher precedence than the indirection operator. It seems like a common sense thing, but again, I must know exactly why. Please provide references if you can.
It cannot be parsed as *(++i), can it?
By the way, * and prefix ++ have the same precedence, and right-to-left associativity.
Prefix ++ has same precedence as unary * while postfix ++ hsa higher precedence than unary * operator.
In case of ++ *i compiler interpret it as
++ (*i);
That means, dereference i, use it, increment the dereferenced value without changing the value of pointer.

(p++)->x Why are the parentheses unnecessary? (K&R)

From page 123 of The C Programming Language by K&R:
(p++)->x increments p after accessing x. (This last set of parentheses is unnecessary. Why?)
Why is it unnecessary considering that -> binds stronger than ++?
EDIT: Contrast the given expression with ++p->x, the latter is evaluated as ++(p->x) which would increment x, not p. So in this case parentheses are necessary and we must write (++p)->x if we want to increment p.
The only other possible interpretation is:
p++(->x)
and that doesn't mean anything. It's not even valid. The only possible way to interpret this in a valid way is (p++)->x.
Exactly because -> binds stronger than ++. (it doesn't, thanks #KerrekSB.)
increments p after accessing x.
So first you access x of p, then you increment p. That perfectly matches the order of evaluation of the -> and the + operators.
Edit: aww, these edit's...
So what happens when you write ++p->x is that it could be interpreted either as ++(p->x) or as (++p)->x (which one is actually chosen is just a matter of language design, K&R thought it would be a good idea to make it evaluate as in the first case). The thing is that this ambiguity doesn't exist in the case of p++->x, since it can only be interpreted as (p++)->x. The other alternatives, p(++->x), p(++->)x and p++(->x) are really just syntactically malformed "expressions".
The maximal munch strategy says that p++->x is divided into the following preprocessing tokens:
p then ++ then -> then x
In p++->x expression there are two operators, the postfix ++ operator and the postifx -> operator. Both operators being postfix operators, they have the same precedence and there is no ambiguity in parsing the expression. p++->x is equivalent to (p++)->x.
For ++p->x expression, the situation is different.
In ++p->x, the ++ is not a postfix operator, it is the ++ unary operator. C gives postfix operators higher precedence over all unary operators and this is why ++p->x is actually equivalent to ++(p->x).
EDIT: I changed the first part of the answer as a result of Steve's comment.
Both post-increment and member access operator are postfix expressions and bind the same. Considering that they apply to the primary or postfix expression to the left, there can't be ambiguity.
In
p++->x
The postfix-++ operator can apply only to the expression to the left of it (i.e. to p).
Similarly ->x can only be an access to the expression to its left, which is p++. Writing that expression as (p++) is not needed, but also does no harm.
The "after" in your description of the effects, does not express temporal order of increment and member access. It only expresses that the result of p++ is the value p had before the increment and that that value is the value used for the member access.
The expresion p++ results in a pointer with the value of p. Later on, the ++ part is performed, but for the purposes of interpreting the expression, it may just as well not be there. ->x makes the compiler add the offset for the member x to the original address in p and access that value.
If you change the statement to :
p->x; p++;
it would do exactly the same thing.
The order of precedence is actually exactly the same, as can be seen here - but it doesn't really matter.

Why are there different associativities among operators in C?

Talking about the associativity of operators in C, I was wondering why there are differences associativities among operators that have the same precedence. for example, postfix increment and postfix decrement have left associativity; while prefix increment and prefix decrement have right associativity. Isn't it simple to have just left or right associativity for all the same precedence operators?
Are there any reasons behind that?
Isn't it simple to have just left or right associativity for all the
same precedence operators?
Yes and it is the case in C. May be you assumed that prefix and postfix have the same precedence which is wrong. Postfix has a higher precedence than prefix!
Also there is another curious case to consider as to why certain operators have certain associativity. From Wiki,
For example, in C, the assignment a = b is an expression that returns
a value (namely, b converted to the type of a) with the side effect of
setting a to this value. An assignment can be performed in the middle
of an expression. (An expression can be made into a statement by
following it with a semicolon; i.e. a = b is an expression but a = b;
is a statement). The right-associativity of the = operator allows
expressions such as a = b = c to be interpreted as a = (b = c),
thereby setting both a and b to the value of c. The alternative (a =
b) = c does not make sense because a = b is not an lvalue.
Binary operators are all left-associative except the assignment operator which is right-associative.
Postfix operators are sometimes (for exemple in K&R 2nd) said to be right-associative but this is to express the idea they have higher precedence than unary operators.

Resources