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.
Related
I have this question for a practice test in C that I don't understand.
Show the output of the following program
x = y = 3;
y = x++, x++;
printf("x = %d, y = %d\n", x, y);
Answer:
1 x = 5, y = 3
I dont understand what
x++, x++
Does x++ mean to implement the value of x into y then add one to it, but why is there a comma ? Would it just first add the value of x in y, and do x=x+1 twice?
I tried putting it in a compiler, found some struggles.
In this statement:
y = x++, x++;
It contains both the assignment operator and the comma operator as well as the postfix increment operator. Of these the postfix increment operator has the highest precedence followed by the assignment operator, then the comma operator. So the expression parses as this:
(y = (x++)), (x++);
The comma operator first evaluates its left operand for any side effects and discards the value of that operand. There is a sequence point here before it then evaluates its right operand, which means evaluating left side and all side effect are guaranteed to occur before those on the right side.
So let's first look at the left operand of the comma operator:
y = (x++)
The subexpression x++ evaluates to the current value of x and increments x as a side effect. At this point x has the value 3, so y gets assigned the value 3 and x is incremented to 4.
Now for the right side:
x++
Since x currently has the value 4, it is incremented to now contain the value 5.
So at the end x is 5 and y is 3.
There is a wikipedia page explaining the comma operator in C and C++: https://en.wikipedia.org/wiki/Comma_operator
It basically evaluates the two expressions left-to-right and returns the value of the second one.
Here you can see the precedence of operators in c++:
https://en.cppreference.com/w/cpp/language/operator_precedence
The comma operator has the lowest precedence.
In your example.
The first line sets both x and y to 3.
The second line increments x twice: x++, x++.
However, since the assignment operator has higher precedence than the comma operator, y gets the value returned by the first increment.
The statement is evaluated as (y = x++), x++.
The first x++ is executed and x gets the value of 4 and returns 3.
This value is assigned to y: y = x++.
Then, the last x++ is evaluated and x gets the value 5.
I know that:
int b = 1, c = 2, d = 3, e = 4;
printf("%d %d %d", ++b, b, b++);
results in undefined behavior. Since
Modifying any object more than once between two sequence points is UB.
Undefined behavior and sequence points
But I don't know if:
int b = 1, c = 2, d = 3, e = 4;
printf("%d", b++ + ++c - --d - e--);
is also UB?
What I think is that increment/decrement operators will evalute first because of the precedence, between them right to left since the associativity . Then arithmetic operators will be evaluated left to right.
Which will just be
(b) + (c + 1) - (d - 1) - (e)
that is, 1 + (2 + 1) - (3 - 1) - (4)
= (2 - 4)
= -2
Is it right?
But I don't know if: ... is also UB?
It is not, but your reasoning about why is fuzzy.
What I think is that increment/decrement operators will evaluate first because of the precedence, between them right to left since the associativity . Then arithmetic operators will be evaluated left to right.
Precedence determines how the result is calculated. It doesn't say anything about the ordering of the side-effects.
There is no equivalent of precedence telling you when the side effects (the stored value of b has been incremented, the stored value of e has been decremented) are observable during the statement. All you know is that the variables have taken their new values before the next statement (ie, by the ;).
So, the reason this is well-defined is that it does not depend on those side-effects.
I deliberately hand-waved the language to avoid getting bogged down, but I should probably clarify:
"during the statement" really means "before the next sequence point"
"before the next statement (... ;)" really means "at the next sequence point"
See Order of evaluation:
There is a sequence point after the evaluation of all function arguments and of the function designator, and before the actual function call.
So really the side-effects are committed before the call to printf, so earlier than the ; at the end of the statement.
There is a gigantic difference between the expressions
b++ + ++c - --d - e--
(which is fine), and
x++ + ++x - --x - x--
(which is rampantly undefined).
It's not using ++ or -- that makes an expression undefined. It's not even using ++ or -- twice in the same expression. No, the problem is when you use ++ or -- to modify a variable inside an expression, and you also try to use the value of that same variable elsewhere in the same expression, and without an intervening sequence point.
Consider the simpler expression
++z + z;
Now, obviously the subexpression ++z will increment z. So the question is, does the + z part use the old or the new value of z? And the answer is that there is no answer, which is why this expression is undefined.
Remember, expressions like ++z do not just mean, "take z's value and add 1". They mean, "take z's value and add 1, and store the result back into z". These expressions have side effects. And the side effects are at the root of the undefinedness issue.
I am trying to find the number of digits in a given number through the use of pointers.
This code below will give the correct output,
void numDigits(int num, int *result) {
*result = 0;
do {
*result += 1;
num = num / 10;
} while (num > 0);
}
However, if I change the *result += 1; line to *result++;, the output will no longer be correct and only give 0.
What is going on here?
In C/C++, precedence of Prefix ++ (or Prefix --) has higher priority than dereference (*) operator, and precedence of Postfix ++ (or Postfix --) is higher than both Prefix ++ and *.
If p is a pointer then *p++ is equivalent to *(p++) and ++*p is equivalent to ++(*p) (both Prefix ++ and * are right associative).
*result++ is interpreted as *(result++).
the order of evaluation is the increment is first, then you dereference the pointer, the value of the pointer stays the same for the line in the expression if it's a postfix.
what you are trying to do is to increment the dereference of the pointer so you need to put the parenthesis on the dereference then increment it, like this: (*result)++;
This question already has answers here:
What is the difference between prefix and postfix operators?
(13 answers)
Closed 8 years ago.
Why is the decrement operator -- not bringing the value down by 1 when executed?
int a = 20;
int c ;
c = a--;
Inspecting the value of c now, it should be 19, yet it comes out as 20. What am I missing?
a-- is Post-Decrement, what you need --a Pre-Decrement. Please read Increment and decrement operators on Wiki
The following C code fragment illustrates the difference between the pre and post increment and decrement operators:
int x;
int y;
// Increment operators
x = 1;
y = ++x;
// x is now 2, y is also 2
y = x++;
// x is now 3, y is 2
// Decrement operators
x = 3;
y = x--;
// x is now 2, y is 3
y = --x;
// x is now 1, y is also 1
what you're using is called a postfix operator. It will get executed [decrement the value] after the assignment = operator has finished its execution with the existing value.
To be clear, in case of post decrement, the ..-- operator is evaluated and the decrement is scheduled once the other evaluations including that operand are finished. It means, the existing value of the operand is used in the other evaluation [in =] and then the value is decreased.
If you want, try printing the value of a itself. It will print the decremented value.
EDIT:
If my choice of words in my answer created any confusions, for the reference, from the c99 standard, chapter 6.5.2.4, [emphasis mine]
[For increment] The result of the postfix ++ operator is the value of the operand. After the result is obtained, the value of the operand is incremented [......]
The postfix -- operator is analogous to the postfix ++ operator, except that the value of the operand is decremented (that is, the value 1 of the appropriate type is subtracted from it).
You are using the post decrement. Post decrement means first use the value in a variable or
anything then decrement the value in the variable. So in this case first value of a will assigned to c. And the decrement is done. You can check printing the value of a.
you should use --a (pre decrement operator), you are using post decrement operator a--
The result of the postfix -- operator is the value of the operand. As a side effect, the
value of the operand object is decremented (that is, the value 1 of the appropriate type is
subtracted to it).
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;
}