I know that x++ refers to post increment. It first uses the original value and then resorts to the incremented value.
But when does that actually happen?
Does it happen when the next immediate line in code is executed?
Does it happen when original value is returned once?
It happens between sequence points.
Other than that, it's unspecified when it happens.
Imagine this
x = y = z = 42
; // sequence point A
n = x++ + y++ + z++
; // sequence point B
At seq. point A x, y, and z are all 42; at sequence point B they are all 43. For all you care, the compiler could emit code to update all 3 variables at the same time.
// pseudo code
n = 126;
[vector increment][x,y,z];
//n = 126;
Related
I have to analyze what some code in C does, and I have a doubt about what happens in a certain line. The code is
#define PRINTX printf("%d\n", x)
void problem() {
int x = 2, y, z;
x *= 3 + 2; PRINTX;
x *= y = z = 4; PRINTX;
x = y == z; PRINTX;
x == (y = z); PRINTX; // This line is the problem
}
This code snippet prints the resulting numbers:
10
40
1
1 // This result **
the problem is that I'm still trying to figure out why does the last line prints out x = 1, when the operation is x == (y = z). I'm having trouble finding out what that 1 means and the precedence of the operations. Hope someone can help me! :)
Nothing in the last statement changes the value of x, so its value remains unchanged.
Parens were used to override precedence, forcing the = to be the operand of the ==.
An operator's operands must necessarily be evaluated before the operator itself, so we know the following:
y is evaluated at some point before the =.
z is evaluated at some point before the =.
x is evaluated at some point before the ==.
= is evaluated at some point before ==.
That's it. All of these are valid orders:
z y = x ==
y z = x ==
x y z = ==
etc.
But whenever x, y and z are evaluated, we can count on the following happening:
= assigns the value of z (currently 4) to y and returns it.
== compares the value of x (currently 1) with the value returned by = (4). Since they're different, == returns 0 (which isn't used by anything).
As you see, nothing changed x, so it still has the value it previously had (1).
In the last statement, nothing is changing the value of x. We are testing if x equals something, but we aren't changing it's value.
So it continues having the same value as it had in the previous statement, in particular, a value of 1.
the reason is because the == operator checks if the 2 numbers are equal, and returns 1 if equal and 0 if not equal that is why it returns one you can check by making x= 1 and y=2 and using the == operator between them
The comparison result of x and assignment of y with (y = z) is discarded. Last line could have dropped the compare: y = z; PRINTX;.
The assignment is not subsequently used either, so the line could have been PRINTX;.
main(){
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y); //output = 261
printf("%d\n\n", x); // output = 257
printf("%d", y); // output = 5
}
Is the final answer 261, because 256 -> 257 (post operator) and 5 -> 5 (pre operator) cause 256 + 5 = 261?
Given:
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y);
In short: The x++ returns the value 256 and then increments x to 257. The ++y increments y to 5 and returns the value 5. The addition, therefore, adds 256 and 5 yielding 261.
Long windedly: The x++ evaluates to the current value of x which is 256 and schedules an increment of x to 257. Similarly ++y schedules the increment of y to 5 and evaluates to the incremented value 5. The addition, therefore, adds 256 and 5 yielding 261. The order in which the terms involving x and y are evaluated is not defined, but both have to be evaluated before the addition (though the increments may not be complete when the addition is evaluated). Because there is a 'sequence point' when the arguments (and the expression denoting the function) have been evaluated but before the function is called, the increments must be complete when printf() is called.
The next two statements print x and y as 257 and 5.
Note that those two printf() operations could be combined into one. Neither could be combined with the first without invoking undefined behaviour. (See Multiple increments and undefined behaviour for more information on this topic.)
So, allowing for the fact that I would not express it quite the way you wrote it, you seem to have the correct explanation.
Also, Standard C has required a return type on all functions for over 15 years now (since C99 was standardized). You should write:
int main(void)
for a main() function that takes no arguments. (See What should main() return in C and C++? for the full details.)
Note that this question only invokes fully defined behaviour (at least, in the printf() statements). It is not asking about multiple increments on a single variable between sequence points.
It will show UNSPECIFIED behavior
In your case, we can't tell whether x++ will be evaluated first or ++y will be evaluated first. It is compiler dependent.
So don't use expressions involving a combination of post-increment or pre-increment operators in C or C++.
For more information refer to the link:
https://www.quora.com/What-does-an-expression-involving-multiple-post-pre-decrement-increment-operators-evaluate-to-in-C-and-C++#
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
I'm currently learning C, and my teacher gave us some homework. We had to identify the output of some code. I don't understand how y=4.
The code is as follows
int main() {
int w = 3, y = 3;
printf("w = %i\n", --w + w--);
printf("y = %i\n\n", y = w + y++);
return 0;
}
The behaviour is undefined since you modify the value of a variable twice between two sequence points.
You should read more about sequence points http://en.wikipedia.org/wiki/Sequence_point .This is what the Standard says about it:
At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.
Let me preface this with an important public service announcement:
When your compiler gives you a warning, any warning, you would do well to pay attention to it. The code example in your question gives rise to Undefined Behavior - in other words, the C standard does not guarantee that every compiler will give the same results, given your code. That is Always a Bad Thing.
With that out of the way, here is an explanation of what is going on.
I modified your code slightly to look at the intermediate value of w:
#include <stdio.h>
int main(void) {
int w = 3, y = 3;
printf("w = %i\n", --w + w--);
printf("w is actually %d\n", w);
printf("y = %i\n\n", y = w + y++);
return 0;
}
My compiler complains about this code with the following warnings:
order.c:6:24: warning: multiple unsequenced modifications to 'w' [-Wunsequenced]
printf("w = %i\n", --w + w--);
^ ~~
order.c:8:35: warning: multiple unsequenced modifications to 'y' [-Wunsequenced]
printf("y = %i\n\n", y = w + y++);
~ ^
2 warnings generated.
And the output is
w = 4
w is actually 1
y = 4
What is happening? Since compilers parse the statement left-to-right, the statement
--w + w--
seems to result in the following steps (for my compiler):
--w : decrement w, it is now 2
w-- : use the value of '2', but decrement w when you are done
The result is that the sum is 2+2 and the first line prints 4, but after the sum is evaluated w is decremented to 1. However you cannot rely on this behavior - which is why the compiler threw a warning. As Eric Postpischil pointed out there may be situations where the order of execution might be different. "Don't do it" is the bottom line - you are courting Undefined Behavior.
Note that the fact that your program printed w equals 4 doesn't mean that this was true at any time. As you can see, when you actually print out w it is 1.
Assuming the compiler executed these statements in the above order, we go to the next line:
y = w + y++
We start with w = 1 and y = 3. The sum of these two is 4, and that is the value of the expression
y = w + y++
which is therefore what is printed (4).
As a side effect, y is incremented. As it happens, either way the value of y is 4 at the end. If you change the code so you start with w = 5, you end up with y = 6. In other words, the effect of y++ got overridden by the y = assignment.
Undefined Behavior
There is undefined behavior (as described in Why are these constructs (using ++) undefined behavior?) in this code in (at least) these two parts:
--w + w--
y = w + y++
This means that the results you're getting aren't portable or guaranteed.
Lying Code
On top of the undefined behavior, the output actually lies to you. printf("w = %i\n", --w + w--); looks like it's printing the value of w (in that it prints w = …), but it's not printing the value of w, it's printing the value of --w + w-- (which is undefined, so it's actually printing the value of whatever the compiler compiled --w + w-- to).
So what the value of w?
The code your compiler has generated for --w + w-- has the side effect of making w's value be 1, since it is originally 3, and both --w and w-- decrement w. However, the value of --w + w-- (in the code that your compiler generated is, based on the output that you're getting, 4. What could cause this? Well, --w could be evaluated first, which decrements w from 3 to 2, and returns the new value of w, which is 2. Then w-- could be evaluated, which decrements w from 2 to 1, but returns the original value of w, which is 2. The sum of 2 and 2, of course, is 4.
So, the value of --w + w-- is 4, and the new value of w is 1.
And what happens with y?
w's new value is 1, so when you execute (recalling that the value of y is 3):
printf("y = %i\n\n", y = w + y++);
The side effect of y++ is that y is incremented (but it's undefined whether this happens before or after the assignment), but the value of the expression is the previous value of y, which in this case is 3. Therefore, you're adding w, whose value is 1, and and the value of y++, which is 3. You're then assigning 4 to y, and the value of that assignment is 4, so you get 4 as the output. There's still behavior that might be undefined in y = w + y++ because it's not clear when the increment of y should be happening: before or after the assignment?
Your teacher is assuming a specific order of evaluation which is not guaranteed by the language.
Assuming strict left-to-right evaluation, and assuming that side effects are applied immediately, then given the starting values for w and y, the following things happen:
--w evaluates to w-1 (2), and as a side effect decrements w; w is now 2
w-- evaluates to w (2), and as a side effect decrements w; w is now 1
As a result of 1 and 2, --w + w-- evaluates to 4
y++ evaluates to y, and as a side effect increments y; y is now 4
As a result of 4, w + y++ evaluates to 1 + 3, or 4
As a result of 5, y = w + y++ assigns 4 to y.
BUT...
As I said above, this behavior is not guaranteed by the language; except in a few specific cases, the order of evaluation within an expression is left unspecified, so y being 4 is only one of many possible results, all of which are considered equally correct as far as the langauge is concerned.
The behavior of any expression that takes on the following forms (both ++ and --, both prefix and postfix):
x++ + x++
a[i++] = i
y = y++
is undefined. Similarly, the behavior of statments like
foo(y++, y++);
is also undefined.
I've been thinking about this in terms of incrementing a pointer, but i guess in general now I don't know the semantic difference between these two operations/ operators. For example, my professor said that if you have int a[10] you can't say a++ to point at the next element, but I know from experience that a+1 does work. I asked why and he said something like "a++ is an action and a+1 is an expression". What did he mean by it's an "action"? If anyone could tell me more about this and the inherent difference between the two operations I'd greatly appreciate it. Thank you.
x++ and ++x
The increment operator x++ will modify and usually returns a copy of the old x. On a side note the prefixed ++x will still modify x but will returns the new x.
In fact x++ can be seen as a sort of:
{
int temp = x;
x = x + 1;
return temp;
}
while ++x will be more like:
{
x = x + 1;
return x;
}
x + 1
The x+1 operation will just return the value of the expression and will not modify x. And it can be seen as:
{
return (x + 1);
}
x++ is an action in the sense that it changes x
x+1 does not change x
x++ is a const expression that modifies the value of x (It increases it by 1). If you reference x++, the expression will return the value of x before it is incremented.
The expression ++x will return the value of x after it is incremented.
x + 1 however, is an expression that represents the value of x + 1. It does not modify the value of x.
a++ will translate to a=a+1 which is an action (due to the contained assignment operation)
a+1 is just an expression which refers to a+1 (either in pointer terms or in terms of a number depending upon a's type)
x++ is equivalent to x = x + 1. It is an action in that it is actually changing the value of x.
Every expression returns a result (unless it's void).
x + 1 returns the value of x + 1.
x++ returns the value of x, and as a side effect the value of x is incremented at some point, not necessarily immediately.
This means you can have:
x = x + 1;
but this is illegal:
x = x++;
What is the difference between increment operator ++ and an addition + operator? Why can't we can use + instead of ++?
What are the advantages of ++/-- operators over +/-? Where exactly are they applicable?
x++;
v.s.
x = x + 1;
The main advantage comes from pre-increment v.s. post increment:
e.g.
x = 1;
y = 1;
a = x + 1; // a is 2, x is 1 - e.g. does not modify x
a = ++x; // a is 1, x is 2
b = y++; // b is 2, y is 2
The major downside is that stuff like
a = ++x + x--;
is undefined behavior. Completely compiler dependent and WILL make life hell for anyone trying to figure out the "bug".
The only difference that is given by the C standard is the number of evaluations of x. For normal variables the difference usually doesn't matter. If the compiler can prove that in x = x + 1 the two evaluations of x should give the same value it might optimize this out.
If x is e.g declared volatile or involves the evaluation of a function, the evaluation must be done twice. Example:
unsigned* f(void);
then
*f() = *f() + 1;
is quite different from
++(*f());
The unary operators (++, --) are mainly there for convenience - it's easier to write x++ than it is to write x = x + 1 for example.
++ can also be used to do a 'pre-increment' or a 'post-increment'. If you write x++ then the value of x is increased and the original value of x is returned. For example:
int a = 0;
int x = 0;
a = x++; // x is now equal to 1, but a is equal to 0.
If you write ++x, x is still incremented, but the new value is returned:
int a = 0;
int x = 0;
a = ++x; // Both a and x now equal 1.
There is also usually a minor difference in the compiler's implementation as well. Post-increment (x++) will do something like this:
Create a temporary variable
Copy x to the temporary variable
Increment x
Return the temporary variable
Whereas pre-increment (++x) will do something like this:
Increment x
Return x
So using pre-increment requires less operations than post-increment, but in modern day systems this usually makes no worthwile difference to be a decent way of optimising code.
You could in fact use addition:
a = a + 1
But most people prefer the shorter version. In some languages it actually avoids the need to copy the value to a new location, but as nneonneo has helpfully pointed out, the C compiler is likely to optimise this for you.
"++" means "plus one"
eg
int x = 5;
x++; // the same as x = x + 1
cout << x; // will print 6
"+" is the known plus operator
++ is a convenience syntax. It does not really add capability to the language, but it adds a way of writing some common operations more concisely.
As a standalone statement a++; is identical to a+=1; is identical to a=a+1;
a++ can be useful in some situations that would otherwise need two statements:
while (a < N) doSomethingWith(a++);
is just a shorter form of
while (a<N)
{
doSomethingWith(a);
a=a+1;
}
I don't think there is anything you can write with an a++ that you couldn't also write with an a=a+1, but you can't just do a 1 for 1 substitution. Sometimes the 2nd form will require more code to be equivalent, since the 1st performs two things: produce the value of a, and then increment a. The a=a+1 form produces the value of a after the increment, so if you need the original value, you need a separate statement to process that first.
The difference between using the increment operator(ie. value++) vs using the addition operator(ie. value + 1) is that the first one sometimes can cause mutation especially if we are accessing a global variable inside a function;
Using increment operator.
// The global variable
var fixedValue = 4;
function incrementer () {
// Only change code below this line
return fixedValue ++;
// Only change code above this line
}
var newValue = incrementer(); // Should equal 5
console.log(fixedValue); // Should print 5
Using addition operator.
// The global variable
var fixedValue = 4;
function incrementer () {
// Only change code below this line
return fixedValue + 1;
// Only change code above this line
}
var newValue = incrementer(); // Should equal 5
console.log(fixedValue); // Should print 4
increment doing on register but addition do by ALU we can use + instead of increment but increment is faster