This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
In Python, you can easily exchange the values of 2 variables with an expression like this:
x, y = y, x
In C++, on the other hand, if you want to exchange the values of 2 variables, you usually use a temporary variable to store the value of one of your variables, something like this:
int var1 = 100;
int var2 = 200;
int temp = var1;
var1 = var2;
var2 = temp;
This is easy, but you have to write a lot of code.
A professor that I have been following for his lectures on C++ has discovered a new compact way of exchange the values of 2 variables in a magic way:
int x = 200;
int y = 100;
x = y - x + (y = x);
It seems incredible, but it works both with the compiler he's using and mine Apple LLVM version 6.0 (clang-600.0.56).
It seems that the way that expression is interpreted is the following:
(y = x) // returns the value of x
-x + x = 0
x = y + 0
x = y
y = x // finally, y receives the initial value of x
If I try to exchange the values of some variables in a loop, it seems also to work:
for (int i = -10; i <= 10; i++) {
for (int j = 10; j >= -10; j--) {
int x = i, y = j;
x = y - x + (y = x);
std::cout << "x = " << x << "\ny = " << y << '\n';
}
}
We have seen that the exchange is done, but my compiler gives me this warning:
main.cpp:28:22: warning: unsequenced modification and access to 'y'
[-Wunsequenced]
If there's a warning, I suppose this is not a new standard way of exchanging the values of 2 variables, but was just an ingenious workaround of this professor.
Why this method is not standardised in C++, and why exactly does it work?
This is undefined behavior, and it's not guaranteed to work. The order of evaluation of the parameters in an expression is not specified. So it's allowed to access the value of y for the subtraction before or after it performs the y = x assignment.
The reason it's specified like this is to allow flexibility for optimizations.
It "works" because you were unlucky.
Yes, I said unlucky. The code has undefined behavior; the fact that it appears to "work" means that your compiler has let you get away with code that could fail next time you run it.
x = y - x + (y = x);
The object y is accessed twice, once to read its value and once to assign a value to it. The language does not define the order in which those accesses occur -- or that the occur in any order at all. As the warning message says, they're "unsequenced". The possible behaviors are not limited to the two possible orders; the behavior is entirely undefined.
Furthermore, the addition and/or subtraction could overflow, which is another potential source of undefined behavior.
This, `x = y - x + (y = x);, is undefined behavior in C - one undefined behavior listed by the C99 spec is:
Between two sequence points, an object is modified more than once, or
is modified and the prior value is read other than to determine the
value to be stored
The only sequence points in this expression are the beginning of the expression and the end of the complete expression.
Related
This question already has answers here:
Pre vs Post Increment
(3 answers)
Closed 8 months ago.
I have the following c++ program:
#include <iostream>
using namespace std;
//looping through arrays backwards
int main() {
int a[3] {1, 2, 3};
int x = sizeof(a), y = sizeof(int), z = x / y;
for(int i = z - 1; i >= 0; i--) {
cout << a[i] << " ";
}
return 0;
}
And it outputs 3 2 1. But if I change the first parameter in the for loop to int i = z--;, it outpus 2 3 2 1 and I don't understand why. Aren't z - 1 and z-- supposed to be the same thing? Could someone please explain why? Also, I'm a begginer in C++ and I'm learning via the W3Schools tutorial about it. Thanks!
The expression z-- evaluates to z, then - as a side effect - z is decremented (scheduled according to scheduling rules). This means, you're essentially saying int i = z in your loop (and then decrement z, but it's not used anymore) - therefore, your code has UB. The 2 printed is purely coincidental, anything might be printed or anything could happen in your code. If you'd like to use --, use it as prefix, i. e., int i = --z.
i have a little problem with this small piece of code;
If i use the ++ operation (x++) it works fine, but if i write "x + 1" it breaks and causes an infinite loop of zeros.
The code:
int x = 0;
while (x <= 20)
{
std::cout << x << std::endl;
x + 1;
}
Any help would be appreciated!
If you want to set a value of a variable you must* use an =.
This : x + 1 is NOT the same as x = x + 1 or x += 1 or x++.
When you add that x plus to your code you are never changing the value of x.
x + 1 simply returns a temporary value of the result. Where as the other three listed about will change the value of x instead of creating a temporary value.
You need to know the differences between different statements related to increment as below.
x++ means x = x + 1; which means copy the value of x into temporary
register, increment the value by 1 and write that register value back
into x.
x + 1 means, copy the value of x into temporary register, increment
the value by 1. You are not assigning the value back to x. So x value
won't be changed.
So in your while loop, x value is not being changed which is reason for infinite loop.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
I already know that x += 1 means x = x + 1.
The =-symbol allocates the value of the arithmetic expression on it's right to the variable on it's left.
But if i have an expression like x += y % 3, does that mean x = (x + y) % 3or x = x + (y % 3)?
The += operator is both allocating a value to a variable and expressing arithmatics, which has me confused.
Unfortunately I currently can't just test some code to check, so I hope I can get some help here.
I'm new to C++, so some of these very basic things still confuse me...
The =-symbol allocates the value of the arithmetic expression on it's right to the variable on it's left
It assigns the result. Allocation is something different, and it'll be important to remember the difference later (dynamic allocation in particular will be really confusing if you conflate it with assignment).
But if i have an expression like x += y % 3, does that mean x = (x + y) % 3 or x = x + (y % 3)?
Part of the reason for having the compound +=, -= etc. operators is that you don't expand the expression like this, avoiding the ambiguity created by your re-write.
x += y % 3
can be read as
tmp = y % 3; // evaluate right hand side
x += tmp; // assign to left hand side
(you can expand x += tmp to x = x + tmp if you really want to, after tmp has been evaluated).
The rules are all documented here in any case, and anyway you absolutely can just test some code to check: https://ideone.com/81tvjH
There is a confusion here, because you think x += 1; is always x = x + 1. This is true for integers, doubles... but generally NOT the case for other objects. Lots of implementations don't create a temporary object. Or could do something very evil.
So then it's a call to operator+=, which takes as the argument the result of the right hand side of the assignment.
So for integers, it's x = x + (y % 3).
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
I would always expect that it works as described here: What is x after "x = x++"?
But when I tried to test it:
int x = 0;
x = x++;
printf("x = %d\n", x);
The result is not 0 as I would expect but 1. We tested it in VS2012 and g++ (version 4.7).
Note, that this code prints 0 as expected:
int x = 0;
int y = x++;
printf("y = %d\n", y);
Note that you are linking Java question, but you are writing in C++.
In C (and inherited in C++), x = x++; is undefined, because you are modifying x twice between two sequence points. This means that the code can do literally anything, including stealing money from your bank account and hiring hitmen to kill you, and the compiler is in the right.
Be glad that it only sets x to 1. :-)
This question already has answers here:
Post increment and Pre increment in C
(3 answers)
Closed 9 years ago.
I was expecting this code snippet to print 3 as the if condition is false and y++ will execute, but it prints 2, any idea why..Thanks!!
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x++ : y++);
// This prints 2
x++ and y++ are post-increment. That is, they return the current value of the variable, then add one to it.
Pre-increment would be ++x or ++y. Those increment and then return the new value.
Both pre- and post-increment (and -decrement) are useful things when writing loop controls, which is why C supports both.
(Originally, if I remember correctly, C only supported pre-increment and post-decrement, because there happened to be instructions on the machines it was developed on which encapsulated those behaviors. But as C moved to other systems, and as people started noticing that they wanted both pre and post for both, this was generalized.)
Note that this means the c++ language was misnamed. It should have been called ++c -- we want it improved before we use it, not after!
It's because y++ returns the value of y then increases it.
Where as if you put ++y it would increase the value of y first then return it.
The ++ operators are evaluated last; this is called "post-increment." So, this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x++ : y++);
is equivalent to this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x : y);
y++;
(x++ isn't ever reached because of the ternary condition.) On the other hand, this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? ++x : ++y);
would increment y before returning its respective value to printf(), so the logic would be:
printf("%d\n", (3<2) ? 3 : 3); // prints 3
Since you use a post increment y++, value of y will be used first and incremented. That is the printf will be passed the value before increment operation, in your case y is 2 before increment and 2 will be printed.
You should consider x++ and y++ after all the other operations of this line have been completed. So, print y and then increment x and y.