I have read in here and in here that postfix(es) are prior to prefix(es).
int a = 5;
int b = 5;
printf("%d\n",a++);
printf("%d\n",++b);
But this code output would be 5,6. how does this make sense then?
What is talked about in your links is operator precedence. That does not affect the working of the post increment. The post increment operator increases the value after the expression in calculated.
Post-increment operator is used to increment the value of variable as
soon as after executing expression completely in which post increment
is used.
What this means is that even if you have a statement like
int i = 0 , j = 5 , k ;
k = ++i + j++ ;
The ++i will be calculated ( i becomes 1 ) and the expression is calculated, and thus k gets the value 6 , and after assigning the value 6 to k, the effect of j++ comes into place and j becomes 6.
Operator precedence determines how operators are grouped, when
different operators appear close by in one expression. For example, '
* ' has higher precedence than ' + '. Thus, the expression a + b * c means to multiply b and c , and then add a to the product (i.e., a +
(b * c) ).
But the precedence does not change the working of the postfix increment. It will increase the value only after the expression is calculated ( that part is independent of it's precedence ) .
I'll give you a simple example ( Hope you know about using pointers )
#include<stdio.h>
int main()
{
int a[] = { 11, 22 };
int x;
int *p = a;
x = *p++;
printf( " *p = %d\n",*p );
printf( " x = %d",x );
}
The output for this is
*p = 22
x = 11
You can refer this ideone link for proof.
Now lets explain that. The ++ has a higher precedence than * , so that code will be same as
x = * ( p++ );
That is, ++ will will make the pointer p point to the next address of the array , but that part is done only after the expression is calculated ( in other words, after the value of *p is assigned to x ) . So after the expression, p will point to the next address, which would have the value 22 while x will still get the value 11.
Hope this makes it clear ( this example might be a bit hard to understand, but it's one of the best to understand this )
Related
I have been reviewing material regarding C for the upcoming semester, and stumbled across some topics involving pointers and memory. I did not write the code, but I am trying to understand all of it. The expressions are as follows (for conciseness I removed int main()):
int x = 5;
int y;
int *p = NULL;
p = &x;
y = *p + 2; /* y is assigned 7 */
y += *p; /* y is assigned 12 */
*p = y; /* x is assigned 12 */
(*p)++; /* x is incremented to 13 */
I do not understand the 7th statement, because it isn't consistent with the way the 5th statement is evaluated. As far as I was concerned, *p is used to access the value p points to, being x, which is 5. In the 5th statement, we set y = *p + 2, which evaluates to y = 5 + 2 = 7. So, why in the 7th statement is *p used as a pointer to x, and not the value 5? (ie. why doesn't the expression evaluate to 5 = 12 and give an error?).
Thanks for any of the help, appreciate it.
*p = y; sets *p to the value of y and does not set 5 to the value of y for the same reason that x = y; sets x to the value of y and does not set 5 to the value of y.
Specifically, in most places, when there is expression that refers to an object, like x or *p or y, it is automatically converted to the value stored in that object. This is why, in x = y;, the y is converted to 12. This conversion occurs due to C 2018 6.3.2.1, which says:
… an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)…
But the full sentence lists exceptions:
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)…
In x = y; or *p = y;, the x or *p is the left operand of an assignment operator. So these are not converted to values. Each remains an lvalue. An lvalue is a reference to an object; it designates the object itself, not its value.
So x = y; puts the value of y into the object referred to by x, and *p = y; puts the value of y into the object referred to by *p.
why doesn't the expression evaluate to 5 = 12
It's possible to write to the memory pointed to by a pointer.
Similarly, x = y; is valid because you can read from the variable y and you can write to x. Same thing with pointers: *p = *p + 1;, for example, will read from p, add one to that value and write the result back to p.
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int main(void) {
int a=2;
int b=3;
int c = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a);// a=3
printf("\nb= %d", b);//b=5
printf("\nc= %d", c);//c=4
a=3;
b=2;
cc = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a); // a=5
printf("\nb= %d", b); //b=3
printf("\nc= %d", c); //c=4
return 0;
}
I would like to know why c is not evaluating to 5.
It appears to me the evaluation order should be:
First both a and be get incremented in (a++)>(b++)
If for example the first one is greater, the ternary operator in
c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a
increments again.
The result of the ternary expression, which is a twice-increment,
should be assigned to c, then c should have the greater value
twice-incremented, that is 5. However, I am getting 4. I suspect the
greater value's second increment is happening at the end, but I can't
explain why, since the parentheses seem to indicate that the
assignment comes at the end.
Any idea?
The postfix ++ operator has a result and a side effect. The result of a++ is the value of a before the increment - given
int a = 1;
int x = a++;
the value of x will be 1 and the value of a will be 2. Note that the side effect of adding 1 to a does not have to be applied immediately after evaluation - it only has to be applied before the next sequence point.
So, looking at
((a++) > (b++)) ? (a++) : (b++)
The ?: operator forces left-to-right evaluation, so the first thing that happens is that (a++) > (b++) is evaluated1. Since a is initially 2 and b is initially 3, the result of the expression is false (0). The ? operator introduces a sequence point, so the side effects to a and b are applied and a is now 3 and b is now 4.
Since the result of the condition expression was 0, we evaluate b++. Same thing, the result of the expression is the current value of b (4), and that value gets assigned to c. The side effect to b is applied at some point, and by the time everything's finished, a is 3, b is 5, and c is 4.
Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.
Let's consider for example this declaration
int c = MAX(a++,b++);
after the macro substitution there will be
int c = (( a++) >( b++ ) ? (a++) : (b++));
The variables a and b are initialized like
int a=2;
int b=3;
As a is less than b then the third expression (b++) will be evaluated as a result of the conditional operator. In the first expression ( a++) >( b++ ) a and b were incremented. There is a sequence point after the evaluation of the first expression.
So a will be set to 3, b will be set to 4.
As it was already said the value of the conditional operator is the value of the third expression (b++) where there is used the post-increment. The value of the post-increment operator 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).
So the value of the conditional operator is 4. This value will be assigned to the variable c. But as a side effect the value of b will be incremented.
Thus after this declaration a will be equal to 3, b will be equal to 5 and c will be equal to 4.
For clarity this declaration
int c = (( a++) >( b++ ) ? (a++) : (b++));
in fact can be rewritten in the logically equivalent way.
int result = a > b;
++a;
++b;
int c;
if ( result != 0 )
{
c = a++;
}
else
{
c = b++;
}
For a++ it's equivalent as saying
int temp = a;
a = a + 1;
return temp;
so in the case of a=2, b=3, we can go to the condition (a++)>(b++) and we can have a rewritten as
int temp1 = a;
a = a + 1;
return temp1;
and b rewritten as
int temp2 = b;
b = b + 1;
return temp2;
now since it's only a conditional statement, we're really just evaluating the old values of a and b before the increment which is temp1 = 2 and temp2 = 3 while at the same time a and b values have changed a = 3, b = 4. Since temp1 < temp2 from the old value, we go to the false clause of the ternary operator (b++) and do the same thing as we did before
int temp3 = b;
b = b + 1;
return temp3;
so now b is 5 while the returned temp3 is the previous value of b which is 4. Hope this helps!
#include <stdio.h>
int main(void) {
int d, a = 1 & 0 && (d=4);
printf("%d\n", d);
return 0;
}
According to the operator precedence () statement d should be assigned but in the above program logical and is executed first. d value is not assigned to 4. Please anyone help me to understand the above program. I have tried with gcc and some online compilers
Let's look at f() + g() * h() first.
Precedence and associativity defines what is an operand of what. For example, C operator precedence and associativity tells us that
f() + g() * h()
means
f() + ( g() * h() ) # * has higher precedence than +
rather than
( f() + g() ) * h() # If + had higher precedence than *
Notably, precedence doesn't determine the order in which operands are evaluated. In our example, the three functions could be called in any order, as long as the result of g() and the result of h() are multiplied together, and that the result of the multiplication is added to the result of f().
Back to
1 & 0 && ( d = 4 )
Precedence and associativity simply tell us that the above is equivalent to the following:
( 1 & 0 ) && ( d = 4 ) # & has higher precedence than &&
So what does this do?
&& dictates that its right-hand side is only evaluated if its left-hand side is true. This is called short-circuit evaluation or short-circuiting.
1 & 0 is false, so d = 4 is never evaluated. This leaves d unchanged, and thus uninitialized.
1 & 0 && (d=4) is evaluated like this: (1 & 0) && (d=4)
(1 & 0) is 0
because of short circuiting the right hand side of the && operator is not evaluated
therefore d=4 is never evaluated
therefore d is never assigned
and therefore d contains garbage because local variables are not initialized
If you change int d to int d = 42, the output of your program will be 42
Sorry for this easy question but I couldn't find the answer, if I got a while loop that looks like this. Does it calculate before or after the comparison?
a = 0;
while(a++ < 5)
{
....
When it first runs the loop will it look at it as "1 < 5" or "0 < 5". Thanks
Comparison is done BEFORE the increment, but the body of the loop sees the value AFTER icrementation. So in the first run you'll compare 0 < 5, but in the loop a will have the value of 1.
The postfix operator is applied "after". The prefix operator is applied "before". In the case you've provided the first time 'a' is compared it's value will equal 0
Be careful, cause you can get in trouble with these operators if not used with care. Consider a[ix++] = a[ix] + 1; maybe it will do what you want, maybe not ... try it
Just read the other comment ... very good point that a will take on the ++ value insde the loop.
The result of the expression a++ is the current value of a, so the loop will start out as while ( 0 < 5 ).
The result of the expression ++a is the value of a + 1, so if you had written while ( ++a < 5 ), it would start out as while ( 1 < 5 ).
In both cases, a will be incremented by 1 as a side effect. Note that the side effect does not have to be applied immediately after the expression is evaluated; the only guarantee is that it is applied before the next sequence point (in this particular case, the sequence point is at the end of the conditional expression, so the body of the loop will see the updated value of a). So, if you have an expression like
x = a++ * ++b;
it will be evaluated as x = a * (b + 1), but there's no guarantee that a will be incremented before ++b has been evaluated, nor is there any guarantee that either will be incremented before the multiplication and the assignment. The following is one of many acceptable order of operations:
t1 <- b + 1
x <- a * t1
b <- b + 1
a <- a + 1
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.