how the expression *p++ and ++*p works differently - c

#include<stdio.h>
int main()
{
int a[2]={10,4};
int *k;
int *j;
j=a;
k=j;
printf("j=%d,k=%d\n\n",*j,*k);
*j++;
++*k;
printf("j=%d,k=%d",*j,*k);
return 0;
}
The output is:
j=10 k=10
j=4 k=11
I thought that it should have same result but this is not the case.
I wished to ask what is causing this difference. I didn't got the reason behind it.

You need to dig out your operator precedence table.
*p++ is evaluated as *(p++)
++*p is evaluated as ++(*p)
The second one is due to the prefix ++ having the same precedence as pointer dereference * so associativity (which is from right to left for those operators) comes into play.
For completeness' sake, *(p++) dereferences the current value of p, and p is increased by one once the statement completes. ++(*p) adds 1 to the data pointed to by p.

You have two things going on here:
The different semantics between prefix and postfix ++;
Different precedence of prefix and postfix operators.
Postfix operators have higher precedence than unary (prefix) operators, so the expression *p++ is parsed as *(p++) - you're applying the * operator to the result of p++. By contrast, the prefix ++ operator and unary * have the same precedence, so the expression ++*p is parsed as ++(*p) - you're applying the ++ operator to the result of *p.
Also remember that prefix and postfix ++ have slightly different behavior. Both increment their operand as a side effect, but the result of postfix ++ is the current value of the operand, while the result of prefix ++ is the value of the operand plus 1.

Related

C Operator Precedence postfix increment and dereference

Here is another naïve question from a C newbie: on this page, https://en.cppreference.com/w/c/language/operator_precedence, the precedence of the postfix increment is listed to be higher than that of pointer dereference. So I was expecting in the following code that the pointer is incremented first (pointing at 10) and then dereferenced.
#include <stdio.h>
int main()
{
int a[] = {3, 10, 200};
int *p = a;
printf("%d", *p++);
return 0;
}
However this code outputs still the first array item (3). What am I missing by the concept?
Precedence is placing of parenthesis.
The expression *p++ can be parenthesized as
(*p)++ // incorrect precedence
*(p++) // correct precedence
Note that the value of p++ is the value of p before any change, so the net effect of the correct precedence is the same as *p without ant reflection over the side-effect ++. The change to p itself does not alter the result of *(p++).
As you have correctly assumed, the expression *p++ is evaluated as *(p++); that is, the ++ operator has higher precedence than the * operator.
However, the value of the expression, p++, is just the value of p (i.e. its value before the increment). A side-effect of the operation is that the value of p is incremented after its value has been acquired.
From this Draft C11 Standard:
6.5.2.4 Postfix increment and decrement operators
…
2     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. With
respect to an indeterminately-sequenced function call, the operation of
postfix ++ is a single evaluation. …
Operator precedence specifies how an expression is parsed. Since postfix ++ has higher precedence than *, the expression is equivalent to *(p++). Rather than (*p)++ which would have given it a completely different meaning.
But just because this forces p++ to be evaluated first, it doesn't affect the characteristic of the ++ operator. The C language specifies this operator to behave as (from C17 6.5.2.4/2):
"The value computation of the result is sequenced before the side effect of
updating the stored value of the operand."
This means that p++ always gives the value of p before ++ is applied. In this case p is a pointer, so the value will be the address it pointed at prior this expression. So the code is completely equivalent to this:
int* tmp = p;
p++;
printf("%d", *tmp);
Precedence controls which operators are grouped with which operands. Postfix ++ having higher precedence than unary * simply means that *p++ is parsed as *(p++) instead of (*p)++.
*(p++) means you are dereferencing the result of p++. The result of p++ is the current value of p. As a side effect p is incremented. It is logically equivalent to
tmp = p;
printf( "%d\n", *tmp );
p = p + 1;
where the printf call and the update to p can happen in any order, even simultaneously (interleaved or in parallel).

C Operators and Precedence

I'm using C language, for the below code:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1=0;
int res = ++num1 && num1++;
printf("%d\t%d\n",num1,res);
}
In the above code I get output as 2 1. I think the output should be 2 0.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Please comment how is this statement getting executed.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence, but if that is true then according to the associativity rule again num1++ should be executed first(right to left) which should again lead to answer as 2 0.
In the expression used as an initializer
int res = ++num1 && num1++;
there is a sequence point for the operator &&.
From the C Standard (6.5.13 Logical AND operator)
3 The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares equal to 0, the second operand
is not evaluated.
At first the left operand of the operator is evaluated and as a result num1 will be equal to 1 due to the unary (prefix) increment operator. As the sub-expression is not equal to 0 then the second operand is evaluated. Its value is the value before incrementing that is 1. As this second operand is also unequal to 0 then the whole expression is evaluated to the logical true and its value is 1 (see the first quote from the C Standard).
This value 1 is assigned to the variable res while the variable num1 after the postfix increment will be equal to 2.
So you will have that after this declaration res is equal to 1 and num1 is equal to 2.
Lots of misconceptions here. First of all, operator precedence states the order of parsing, not the order of execution. There are two related but different terms, operator precedence and order of evaluation.
See What is the difference between operator precedence and order of evaluation?.
Once you understand order of evaluation, the && operator specifically comes with well-defined sequencing, which isn't normally the case for C operators. It guarantees a left-to-right order of evaluation. C17 6.5.14/4:
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
Normally, you wouldn't be able to wild and crazy things with the ++ operator mixed with other operators, but the above && rule makes it possible in this specific case.
See Why can't we mix increment operators like i++ with other operators? It explains sequencing/sequence points.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
They don't, prefix ++ takes precedence over postfix (and other unary operators). So associativity does not apply.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Precedence only controls which operators are grouped with which operands - it does not affect the order in which expressions are evaluated.
The &&, ||, ?:, and comma operator all force left-to-right evaluation - the left operand is fully evaluated (and any side effects applied) before the right operand. && and || both short circuit - for &&, the right operand will be evaluated only if the left operand is non-zero.
The unary (prefix) ++ operator yields the current value of the operand plus 1, so the result of ++num1 is 1. As a side effect the value in num1 is incremented. Since this result is non-zero, num1++ is also evaluated. The postfix ++ operator yields the current value of the operand, so the result of num1++ is 1. As a side effect the value in num1 is incremented.
The result of an && expression is 1 if both operands are non-zero, 0 otherwise.
It's roughly equivalent to writing
tmp = num1 + 1;
num1 = num1 + 1;
res = 0;
if ( tmp != 0 )
{
if ( num1 != 0 )
{
res = 1;
}
}
num1 = num1 + 1;
So the result of ++num1 && num1++ is 1, and the value stored in num1 at the end of it is 2.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
That is very wrong and you should stop using those tutorials immediately. Postfix operators have higher precedence than unary operators - *a++ is parsed as *(a++), ++a[i] is parsed as ++(a[i]), etc. An expression like ++i++ would be parsed as ++(i++), but you can't write such an expression in C - the result of i++ isn't an lvalue and cannot be the operand of a unary ++ like that.

*p++->str : Understanding evaluation of ->

My question is about the following line of code, taken from "The C Programming Language" 2nd Edition:
*p++->str;
The book says that this line of code increments p after accessing whatever str points to.
My understanding is as follows:
Precedence and associativity say that the order in which the operators will be evaluated is
->
++
*
The postfix increment operator ++ yields a value (i.e. value of its operand), and has the side effect of incrementing this operand before the next sequence point (i.e. the following ;)
Precedence and associativity describe the order in which operators are evaluated and not the order in which the operands of the operators are evaluated.
My Question:
My question is around the evaluation of the highest precedence operator (->) in this expression. I believe that to evaluate this operator means to evaluate both of the operands, and then apply the operator.
From the perspective of the -> operator, is the left operand p or p++? I understand that both return the same value.
However, if the first option is correct, I would ask "how is it possible for the evaluation of the -> operator to ignore the presence of the ++".
If the second option is correct, I would ask "doesn't the evaluation of -> in this case then require the evaluation of a lower precedence operator ++ here (and the evaluation of ++ completes before that of ->)"?
To understand the expression *p++->str you need to understand how *p++ works, or in general how postfix increment works on pointers.
In case of *p++, the value at the location p points to is dereferenced before the increment of the pointer p.
n1570 - §6.5.2.4/2:
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.
In case of *p++->str, ++ and -> have equal precedence and higher than * operator. This expression will be parenthesised as *((p++)->str) as per the operator precedence and associativity rule.
One important note here is precedence and associativity has nothing to do with the order of evaluation. So, though ++ has higher precedence it is not guaranteed that p++ will be evaluated first. Which means the expression p++ (in the expression *p++->str) will be evaluated as per the rule quoted above from the standard. (p++)->str will access the str member p points to and then it's value is dereferenced and then the value of p is incremented any time between the last and next sequence point.
Postfix ++ and -> have the same precedence. a++->b parses as (a++)->b, i.e. ++ is done first.
*p++->str; executes as follows:
The expression parses as *((p++)->str). -> is a meta-postfix operator, i.e. ->foo is a postfix operator for all identifiers foo. Postfix operators have the highest precedence, followed by prefix operators (such as *). Associativity doesn't really apply: There is only one operand and only one way to "associate" it with a given operator.
p++ is evaluated. This yields the (old) value of p and schedules an update, setting p to p+1, which will happen at some point before the next sequence point. Call the result of this expression tmp0.
tmp0->str is evaluated. This is equivalent to (*tmp0).str: It dereferences tmp0, which must be a pointer to a struct or union, and gets the str member. Call the result of this expression tmp1.
*tmp1 is evaluated. This dereferences tmp1, which must be a pointer (to a complete type). Call the result of this expression tmp2.
tmp2 is ignored (the expression is in void context). We reach ; and p must have been incremented before this point.

++*p++ cant understand the precedence thing

running this code:
#include <stdio.h>
int main() {
int x[]={20,30};
int *p=x;
++*p++;
printf("%d %d\n",x[0],*p);
return 0;
}
the output is 21 30 which is something that doesn't make sense to me because according to C operator precedence the postfix increment comes first though if that was the case in my opinion the output should be 20 31.For the record i am new to programming and it really seems that i cant get the hang of it so sorry if this question is stupid :)
From the C++ Standard (the same is valid for the C Standard)
5.2 Postfix expressions
1 Postfix expressions group left-to-right.
Postfix expressions and p++ is a postfix expression have higher priority than unary expressions.
The C++ Standard
5.3 Unary expressions
1 Expressions with unary operators group right-to-left.
In this expression ++*p there are two unary subexpressions: *p and ++( *p )
So the whole expression can be written like
++( *( p++ ) );
Take into account regarding the postfix expression ++ that (now it is the C Standard)
6.5.2.4 Postfix increment and decrement operators
2 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).
Let's consider the result of the expression statement
++( *( p++ ) );
subexpression p++ has the value of its operand that is the address of type int * of the first element of the array. Then due to the dereferencing the expression *( p++ ) yields the lvalue of the first element of the array that is x[0] and then its value is increased. So the first element of the arry now has the value 21.
At the same time the postfix increment incremented the pointer p as its side effect (see the quote above from the C Standard). Its now points to the second element of the array.
Thus the output will be
21 30
You first increment where p points to and then you advance the pointer by one.
So, p points to 20, thus ++20 = 21.
Then the pointer will be increased by once, and due to pointer's arithmetic, it will point to next element of 20, which is 30, in your array.
As M.M said, you are confusing, the order of evaluation with precedence. Read more about it here.
according to C operator precedence the postfix increment comes first
Precedence is not the same thing as order of evaluation.
Precedence controls which operators are grouped with which operands. In this case, the expression ++*p++; is parsed as ++(*(p++)).
The order of evaluation is
Evaluate p++; the result of this evaluation is &x[0], and the side effect is to advance p to point to x[1];
Dereference the result of 1; the result of this evaluation is x[0];
Apply the prefix ++ operator to the result of 2; the result of this evaluation is x[0] + 1, with the side effect that the value stored in x[0] is incremented.
Remember that side effects do not have to be applied immediately upon evaluation; they may be deferred until a sequence point.

Why is *p++ different from *p += 1?

Consider:
void foo1(char **p) { *p++; }
void foo2(char **p) { *p += 1; }
and
char *s = "abcd";
char *a = s;
foo1(&a);
printf("%s", a); //abcd
but if I use foo2() instead of:
char *a = s;
foo2(&a);
printf("%s", a); //bcd
Can someone explain it?
The key is the precedence of the += and the ++ operator. The ++ has a higher precedence than the += (in fact, assignment operators have the second lowest precedence in C), so the operation
*p++
means dereference the pointer, then increment the pointer itself by 1 (as usually, according to the rules of pointer arithmetic, it's not necessarily one byte, but rather sizeof(*p) regarding the resulting address). On the other hand,
*p += 1
means increment the value pointed to by the pointer by one (and do nothing with the pointer itself).
Precedence. The postfix ++ binds tighter than the prefix * so it increments p. The += is at the low end of the precedence list, along with the plain assignment operator, so it adds 1 to *p.
Precedence of prefix ++ and * is same. Associativity of both is right to left. Precedence of postfix ++ is higher than both * and prefix ++. Associativity of postfix ++ is left to right.
Let's start with *p += 1
I will try to answer this from a bit of a different angle... Step 1 Let's look at the operators and the operands: In this case it is one operand (the pointer p), and we have two operators, in this case * for dereferencing and += 1 for increment. Step 2 which has the higher precedence * has higher precedence over +=
*P++
This one is a bit trickier... maybe even wicked
Again we have one operand (p the pointer) and two operators, only now the * for dereference and ++ post increment are of the same precedence. (In some tables the ++ in a post is a higher precedence.)
Step 1 Let's look at the operators and the operands: In this case it is the operand, and you have two operators, in this case * for dereferencing and ++ for increment. Step 2 which has the higher precedence? ++ has higher precedence over * Note: even if they have the SAME precedence they associate right to left, again, the ++ is before *
Step 3 (the tricky part...) Where is ++ ? it is to the right side of the operand, which means POST Increment In this case, the compiler take a 'mental note' to perform the increment AFTER it is done with all the other operators...
What after means? It means that it will only apply the increment as the very very very last step before the next ';' so it will be done with all other operators that are on the same 'line'
note: if it was *++p then it will do it BEFORE any other operator on the same line so in this case, it is as equivalent to taking two of the processor's register, one will hold the value of the dereferenced *p and the other will hold the value of the incremented p++, the reason in this case there are two, is the POST activity... This is where in this case it is tricky, and it looks like a contradiction. One would expect the ++ to take precedence over the *, which it does, only that the POST means that it will be applied only after ALL other operands, BEFORE the next ';' token...
Like I said, the tricky part is that any increment that is to the right of an operand will be set aside, and will be applied as the LAST operation before it moves on to the next line...

Resources