How is this C expression evaluated - c

Expression is:
foo = *p++
I am looking for a guide/reference with examples that can explain these things.
I understand postfix ++ has higher precedence than indirection *, so the expression is parsed as
*(p++)
But I am trying to get more clarity on the statement in GNU C reference manual Pg 40, that says:
Here p is incremented as a side effect of the expression, but foo takes the value of *(p++) rather than (*p)++, since the unary operators bind right to left.

In C/C++, precedence of Prefix ++ (or Prefix –) and dereference (*) operators is same, and precedence of Postfix ++ (or Postfix –) is higher than both Prefix ++ and *.
If p is a pointer then *p++ is equivalent to *(p++) (because postfix has higher precedence)
++*p is equivalent to ++(*p) (both Prefix ++ and * are right associative).
*++p is equivalent to *(++p) (both Prefix ++ and * are right associative).
You can see the below 2 programs to clarify your doubt.
Program 1
#include<stdio.h>
int main()
{
char arr[] = "overflow";
char *p = arr;
++*p;
printf(" %c", *p);
getchar();
return 0;
}
Output: p
Program 2
#include<stdio.h>
int main()
{
char arr[] = "overflow";
char *p = arr;
*p++;
printf(" %c", *p);
getchar();
return 0;
}
Output: v

The GNU quote is misleading (IMHO); from a language point-of-view it's nothing to do with left-to-right (or vice versa).*
The C language standard doesn't define things in terms of precedence or associativity (left-to-right or right-to-left); these are merely implied by the defined grammar. Postfix ++ is classified as a postfix-expression rather than a unary-expression:
postfix-expression:
primary-expression
[...]
postfix-expression ++
postfix-expression --
[...]
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
[...]
unary-operator:
& * + - ~ !
The interaction of the above production rules mean that your example is interpreted as *(p++).
In non-standardese, though, the reason is due to precedence, not associativity (which makes little sense for unary operators).
* In fact, the postfix operators are effectively left-to-right, which is the opposite of what's claimed.

The OP asked "how is evaluated" the expression *p++.
One thing is precedence and another different thing is evaluation.
The expression p++ increments the value of the variable p, but the value of the expression is he "old" value that p had.
For example, consider that p is char pointer used to analyze a string:
char s[] = "0123456789!";
char *p = s;
char q;
p = s; // Here *p == '0'
q = *p++ // Here q == '0' but *p == '1'
Although the precedence rules imply that *p++ is the same that *(p++), the value of *p++ is s[0], in despite of p == &s[1].
To be more precise, the value of the expression is the same as of *p.
In this case, the "side effects" are referring to the operations that are done over the objects, in this case we have the objects p and q in the expression q = *p++.
"Operation over objects" are not walking in the same path that "evaluation of expressions".

Saying that postfix and unary operators are right-associative (bind right to left) is just another way to express the fact that postfix operators have higher precedence in C than unary operators.

Related

Working of the operators ++ followed by -> in the below example

Consider the code segment given below:
#include <stdio.h>
struct s
{
int x;
char c;
};
int main()
{
struct s x[2]={{1,'a'},{2,'b'}};
struct s * p;
p=x;
int a = p++ -> x; //line of doubt
printf("%d \n",a);
}
The output of the following code is 1 and it makes it clear that it is actually evaluated as :
int a = ((p++) -> x);
Now my question is, we know that in C , the binary -> operator is having higher precedence than the unary ++ operator. But why is the effect such that the ++ is grouped first and then the ->.
Is it so that being a binary operator it looks for the first operand to its left and it being p the pairing is done as :
int a= *(p++ -> x);
But this includes with p, p++ as a chunk and hence first p++ is considered, but I feel this explanation is a bit vague. Could anyone explain me the proper logic and along with it, could anyone recommend me any book from where I could practice more examples like this.
Edit:
Thanks for the answers, actually I have studied C from the texts "The C Programming Language" by Dennis Ritchie et. al and also from "C- The Complete Reference" by Hebert Schildt. In both the texts the operator precedence is as shown:
Source: "The C Programming Language (2nd Ed.)" by Dennis Ritchie et. al (pg. 53)
The postfix increment operator ++ and the member-access-via-pointer operator -> have the same precedence level, and they group left-to-right. So first p++ is evaluated, then (p++)->x.
Section 6.5.2p1 of the C standard gives the following syntax declaration for postfix operators:
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-listopt )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
Had you used the prefix increment operator, i.e. ++p->x, that has lower precedence than ->, grouping as ++(p->x). So you would end up getting the x member from the object p originally pointed to, then that member would be incremented with the expression evaluating to the incremented member.

Are these examples correct?

In this youtube video, I came across with the following examples:
However, they doesn't seem correct to me, for the first example:
*ptr++
In my understanding, this means that, if ++ has greated precedence than *, increment the pointer by 1 in pointer arithmetic, then get the value stored in the address which is pointed by this new pointer. So the code
x = *ptr++;
should be equal to,
ptr++;
x = *ptr;
Which is either conflicting with the video, or I am mixing somethings. Can you please tell me if I am right or wrong?
Precedence affects how expressions are structured. It does not affect what the rules of the operations are.
In *ptr++, precedence says the rules for ++ are applied to ptr, and then the rules for * are applied to the result.
The rules for ++ say that, with ptr++, the resulting value is that of ptr when the operation starts and, separately, the value of ptr is incremented. The actual increment of ptr in memory may occur before, during, or after the production of the result value, but it does not affect the value: The value produced is always the value of ptr before the increment, regardless of when the increment actually occurs.
The rules for * say the result is the object that its operand points to. So, with *ptr++, the result is the object that ptr points to before the increment is applied.
Each expression if it is not a void expression has a value.
The value of the postfix increment is the value of its operand before incrementing.
From 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)
That is this expression
*ptr++
is evaluated like
*( ptr++ )
and the value of the expression in the parentheses is the value of the pointer (the operand of the postfix increment) before incrementing of the operand itself that is evaluated as a side effect.
This is the difference between the postfix increment and the prefix increment for which (6.5.3.1 Prefix increment and decrement operators)
2 The value of the operand of the prefix ++ operator is incremented.
The result is the new value of the operand after incrementation.
It is useful to know that the postfix increment operator may be used to form a subscript expression while the prefix increment operator may not.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int a[] = { 1, 2 };
int *p = &a[0];
printf( "a[0] = %d, a[1] = %d\n", a[0], a[1] );
p++[0] = 3;
*p = 4;
printf( "a[0] = %d, a[1] = %d\n", a[0], a[1] );
return 0;
}
The program output is
a[0] = 1, a[1] = 2
a[0] = 3, a[1] = 4

Order of execution of operator

I am confused of operator precedence table give in http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
I mean right-to-left and left-to-right.
I want to know in what order the operator will we applied on this code.
int main()
{
int i[] = {3, 5};
int *p = i;
int j = --*p++;
printf("j = %d\n\n", j);
system("pause");
return 0;
}
Is it like --(*(p++))? or (--(*p))++ ? Its very confusing. is there any standard rule to resolve this problem.
The expression:
j = --*p++;
is equivalent to:
j = --*p; // first decrements value pointed by p, then assign value pointer by p to j
p++; // increment p to point to next location
The parenthesis version of your expression should be : --(*(p++)); Read #Jonathan Leffler's answer.
I would also suggest you to read #Eric Lippert answer: Incrementing Pointers, Exact Sequence to understand ++ and * operator expression that how a compiler can perform it at low level.
I am confused by the operator precedence table give in http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm. What does right-to-left and left-to-right mean in this table?
Precedence and associativity determine how the parentheses are logically inserted into an underparenthesized expression. If you have
x + y * z
then * is higher precedence, so it wins, and this is:
x + (y * z)
not
(x + y) * z
If you have two operators that have the same precedence then which one wins depends on the associativity. + and - are the same precedence and have left-to-right associativity, so
x + y - z
is
(x + y) - z
And not
x + (y - z)
Operators with right-to-left associativity put the parentheses on the rightmost expression first.
I want to know in what order the operator will we applied on this code. --*p++
Well, follow the chart. We have *, prefix decrement and postfix increment. Consult the precedence table first. Postfix increment is higher precedence than the other two, so automatically this is --*(p++). And now we do not need to consult the table to work out the rest; clearly the only possible parenthesization is --(*(p++)).
++ and -- Prefix increment/decrement right-to-left
and later on you found *
j = --*p++;
Above statement according to precedence -- will perform first. So in expression -- is pre-decrement on *p and then ++ is post increment, will increment pointer p.
j= --*p; //and immediately do *p++ == p++ , because here ++ got priority. and this is post decrement this wont assign to j.this as same as incrementing p value in next statement.
p++;
There are plenty of tricks on prefix increment and postfix increment.
As a programmer, you do not need to spend too much time on those tricks, just use brackets in your code to show the computing order.

What means *p++=x

I'm new in C and I'm wondering what *p++=x means.
I understand what var += x means, what *var++ means but I don't get this one.
It means assign x to *p and then make p point to the next element:
*p = x;
p++;
Postfix operators have higher precedence than unary operators, so *p++ is parsed as *(p++); that is, you are dereferencing the result of the expression p++.
So the expression *p++ = x assigns the value of x to whatever p is pointing to and advances p to point to the next element.

Post-increment in a while loop

The following code confused me a bit:
char * strcpy(char * p, const char * q) {
while (*p++=*q++);
//return
}
This is a stripped down implementation of strcpy function. From this code, we see that pointer p and q are incremented then dereferenced and q is assigned to p until the \0 char has been reached.
I would like someone to explain the first iteration of the while loop.
Because the ++ is after the variables, they aren't incremented until after the expression is evaluated. That's why it's the post-increment operator; the pre-increment is prefixed (++p). *++p would write to the second spot, *p++ writes to the first.
No, the increment happens after the assignment.
If it were *(++p), the pointer p would be incremented and after that assigned.
p++ is post-incrementing the pointer p. So the current value of p is operated upon by the deference operator * before p is incremented.
Your reasoning would've been correct if the while loop was written as follows:
while (*++p=*++q);
In this case the increment would happen before dereferencing.
The expressions x++ and ++x have both a result (value) and a side effect.
The result of the expression x++ is the current value of x. The side effect is that the contents of x are incremented by 1.
The result of the expression ++x is the current value of x plus 1. The side effect is the same as above.
Note that the side effect doesn't have to be applied immediately after the expression is evaluated; it only has to be applied before the next sequence point. For example, given the code
x = 1;
y = 2;
z = ++x + y++;
there's no guarantee that the contents of x will be modified before the expression y++ is evaluated, or even before the result of ++x + y++ is assigned to z (neither the = nor + operators introduce a sequence point). The expression ++x evaluates to 2, but it's possible that the variable x may not contain the value 2 until after z has been assigned.
It's important to remember that the behavior of expressions like x++ + x++ is explicitly undefined by the language standard; there's no (good) way to predict what the result of the expression will be, or what value x will contain after it's been evaluated.
Postfix operators have a higher precedence than unary operators, so expressions like *p++ are parsed as *(p++) (i.e., you're applying the * operator to the result of the expression p++). Again, the result of the expression p++ is the current value of p, so while (*p++=*q++); doesn't skip the first element.
Note that the operand to the autoincrement/decrement operators must be an lvalue (essentially, an expression that refers to a memory location such that the memory can be read or modified). The result of the expression x++ or ++x is not an lvalue, so you can't write things like ++x++ or (x++)++ or ++(++x). You could write something like ++(*p++) (p++ is not an lvalue, but *p++ is), although that would probably get you slapped by anyone reading your code.
The right hand side of the expression (*q++) will be evaluated prior to *p++, and both will only be incremented after the assignment takes place.
Read the statement right to left and remember post-increment (q++ instead of ++q) happens after everything else in the line is resolved.
*q --> dereference q
= --> assign the value
*p --> to p
increment both.
Do this until q p taking q's element = 0 which is when it reaches the null terminator.
The value of q++ is q
The value of ++q is q+1
This is a stripped implementation of strcpy function. From this code, we see that pointer p and q are increamented, than dereferenced and q is assigned to p until \0 char has been reached.
It happens the other way around. The value at *p is set to *q, then both pointers are incremented.
When you have int foo = bar++ the increment happens after foo has been set. To have it happen first you would do int foo = ++bar
The while loop's condition is performing post-increment. Equivalently:
while (true) {
char* old_p = p;
const char* old_q = q;
++p; // or p++;
++q; // or q++;
*old_p = *old_q;
if (*old_p == '\0')
break;
}

Resources