Issue with precedence and ++ and * unary operators in C - 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.

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.

Is this a undefined behaviour or normal output

This is a very simple question but even have some doubt in sequence point.
int a[3] = {1,2,4};
printf("%d",++a[1]);
o/p
3
Is this a valid c statement, I am getting output 3, which means it is same as
++(a[1])
But how is this possible as we have a pre-increment operator which has to increment the a first then the dereference has to happen.
Please correct my doubt. How we are getting 3?
Behavior is well defined. Operator [] has higher precedence than prefix ++ operator. Therefore operand a will bind to []. It will be interpreted as
printf("%d", ++(a[1]));
Your parentheses are right, your rationale for what you think should happen obviously wrong.
If you were right, and prefix-increment had higher priority than indexing, you would get a compiler-error for ill-formed code, trying to increment an array.
As-is, there's absolutely no chance for sequencing-errors or the like leading to UB.
That's how pre increment operator works. Its similar to ++count. So here your value at a[1] (as [] has higher precendence than ++) get incremented and then its printed onto the console.
As you can see here: http://en.cppreference.com/w/cpp/language/operator_precedence
The operator [] has a higher precedence then ++

Confusing answers : One says *myptr++ increments pointer first,other says *p++ dereferences old pointer value

I would appreciate if you clarify this for me.Here are two recent questions with their accepted answers:
1) What is the difference between *myptr++ and *(myptr++) in C
2) Yet another sequence point query: how does *p++ = getchar() work?
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *, the increment to the pointer myptr is done first and then it is dereferenced.I even checked that out on the compiler and verified it.
But the accepted answer to the second question posted minutes before has left me confused.
It says in clear terms that in *p++ strictly the old address of p is dereferenced. I have little reason to question the correctness of a top-rated answer of the second question, but frankly I feel it contradicts the first question's answer by user H2CO3.So can anyone explain in plain and simple English what the second question's answer mean and how come *p++ dereferences the old value of p in the second question.Isn't p supposed to be incremented first as ++ has higher precedence?How on earth can the older address be dereferenced in *p++Thanks.
The postfix increment operator does have higher precedence than the dereference operator, but postfix increment on a variable returns the value of that variable prior to incrementing.
*myptr++
Thus the increment operation has higher precedence, but the dereferencing is done on the value returned by the increment, which is the previous value of myptr.
The answer in the first question you've linked to is not wrong, he's answering a different question.
There is no difference between *myptr++ and *(myptr++) because in both cases the increment is done first, and then the previous value of myptr is dereferenced.
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *,
Right. That is correct.
the increment to the pointer myptr is done first and then it is dereferenced.
It doesn't say that. Precedence determines the grouping of the subexpressions, but not the order of evaluation.
That the precedence of ++ is higher than the precedence of the indirection * says that
*myptr++
is exactly the same (not on the cource code level, of course) as
*(myptr++)
and that means that the indirection is applied to the result of the
myptr++
subexpression, the old value of myptr, whereas (*myptr)++ would apply the increment operator to what myptr points to.
The result of a postfix increment is the old value of the operand, so
*myptr++ = something;
has the same effect as
*myptr = something;
myptr++;
When the side-effect of storing the incremented value of myptr happens is unspecified. It may happen before the indirection is evaluated, or after that, that is up to the compiler.
Section 6.5.2.4 of the C specification discusses the postfix increment and decrement operators. And the second paragraph there pretty much answers your question:
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it).
...
The value computation of the result is sequenced before the side effect of
updating the stored value of the operand.
So given *myptr++, yes it's true the the ++ part has higher precedence; but precedence does not exclusively determine your result. The language defines that with the specs. In this case the value of myptr is returned, then the "side effect" of myptr being incremented is executed.

(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 does *ptr++ act like *(ptr++) and not (*ptr)++? [duplicate]

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.

Resources