Why this is happening in the following code? - c++

I am running this c++ program for swapping two numbers using g++ compiler in ubuntu.
int a = 6, b = 9;
a = a ^ b ^ (b = a);
cout << a << " " << b;
and I am getting this output 9 6. Here first b is processed (old value of b that is 9) before processing b=a part.
But when I run this program
a = a ^ b + (b = a);
cout << a << " " << b;
I get 10 6 as output. It means here b = a part is processed first therefore the value of every b is now 6 hence it is giving output 10 6.
can anybody explain why it is happening so?

a = a ^ b ^ (b = a) involves undefined behavior because the order of evaluation is not specified. If all you want is to swap two integers, use std::swap:
using std::swap;
int a = 6, b = 9;
swap(a, b);

The behaviour of your code is undefined! (b=a) writes to b. There are also reads of b in that same expression a^b^(b=a), and there are no sequencing points in that expression either.
The language does not define the behaviour of a read and write of the same variable in an unsequenced step.
Note for the avoidance of doubt, the parentheses do not specify an order of evaluation, but rather grouping.
P.S. XOR swap is silly, and probably slower than std::swap.

Related

Why adding "variable + 1" doesn't increment its value by one for every loop in a for loop? (C++)

I'm having a hard time understanding why using a increment operator in a for loop in C++ has a different result than doing 'variable' + 1. The variable in the second case simply isn't remembered after each iteration of the loop:
Take the following code:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << ++a;
}
return 0;
}
It outputs as expected:
12345
However, if I instead replace ++a with a + 1:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << a + 1;
}
return 0;
}
I get:
11111
Even if I make the 'a' variable static:
static int a{0};
It still outputs 11111.
Why doesn't 'a + 1' preserve its value after every loop? What would I need to do if I wanted to preserve its value after every iteration without using ++ (for instance, with another operation like a * 2)?
Why doesn't 'a + 1' preserve its value after every loop?
a + 1 is an expression that doesn't assign anything to a. That is a is not affected in any way. This means when you do just a + 1, the value of a is still 0(the old value).
On the other hand ++a has the same effect as:
v---------->assignment done here implicitly
a = a+1
In the above expression ++a, the value of is incremented by 1 so that the new value of a is now 1.
++a is equivalent to the assignment a= a + 1 (or a+= 1). The expression a + 1 alone does not modify a.
C++ will allow you to write std::cout << (a= a + 1);.
a++ is not the same thing as a+1 but as a=a+1.
What's the difference?
Well:
a+1 contains the value, which is one higher than the value of a.
a=a+1 means that, in top of this, this value gets assigned to the variable a, which means something like "replace a by its value plus one".
This gives following possibilities (I also show the difference between a++ and ++a):
int a=3;
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
int a=3;
cout<<a++; // output : 3. Value of 'a' becomes 4 after having shown it on screen.
cout<<a++; // output : 4. Value of 'a' becomes 5 after having shown it on screen.
cout<<a++; // output : 5. Value of 'a' becomes 6 after having shown it on screen.
int a=3;
cout<<++a; // output : 4. Value of 'a' becomes 4 before showning it on screen.
cout<<++a; // output : 5. Value of 'a' becomes 5 before showning it on screen.
cout<<++a; // output : 6. Value of 'a' becomes 6 before showning it on screen.
Conceptually, the built-in arithmetic operators like + and * evaluate their operands, perform the respective operation with the thusly obtained values, and create a temporary object that contains the result.
The operands, one of which is your a, are only read from, not written to. That is more obvious when you consider that + is commutative, that is, its operands can be swapped without affecting the result: a+1 is by definition the same as 1+a, and clearly you cannot write anything back to the immediate value 1.
Generally, as you certainly know, = is used in C and C++ to write a value to a variable. C, and by means of ancestry also C++, provide shortcuts to write back the result of certain operations to one of their operands: it's the combination of the operator and the assignment =, for example a += 1. Like all assignments, this one is an expression (that is, it has a value) which has the value of the variable after the operation and assignment. Like all other expressions, you can use it as a subexpression, even though that's not very common: cout << (a += 1); would achieve the desired effect (the parentheses are necessary because assignment has about the lowest operator precedence). Because incrementing (and decrementing) by one is so very common, C and C++ have a shortcut for the shortcut: ++a is the same as a+=1, so that one would typically write cout << ++a; (as a side effect obviating the need for parentheses).

Confusion about operator precedence in c++

I'm learning c++ and currently learning about operator precedence. I'm playing with the following examples. Imagine each piece as distinct pieces of code run at separate times, not multiple code blocks within the same method.
int b = 4;
int result = ++b;
// In the above example the result will be 5, as expected.
int b = 4;
int result = ++b + b;
// Here the result will be 10 as expected.
int b = 4;
int result = ++b + ++b;
Here the result is 12. I don't understand why. Shouldn't the compiler evaluate ++b changing 4 to 5, then ++b changing 5 to 6, resulting in 5+6 = 11?
It's undefined behaviour, violating sequence rules.
Between the previous and next sequence points a scalar object must have its stored value modified at most once by the evaluation of an expression, otherwise the behavior is undefined.
int b = 4;
int result = ++b + ++b;

Compound Assignment (Multiply)

I recently learn the basic of C++. And i found something that i didn't get the idea. Here is the program that make me a little confuse.
#include <iostream>
using namespace std;
int main()
{
int m = 4, n;
n=++m*--m;
cout <<"m="<<m<<" and n="<<n<<"\n;
return 0;
}
And the output is m=4 and n=16.
I thought that
m=4, so ++m is 5, and --m will be 4,
then n= 5*4= 20.
Hence, the m=4 and n=20.
I think mine is false. So i need a help. Thank you.
The operands of * are unsequenced relative to each other. This means that not only may they be evaluated in any order; but if each operand contains multiple sub-steps, the sub-steps of one operand might be interleaved with those of the other operand.
An example of this might be (f() + g()) * (h() + i()) . The four functions could be called in any order -- it is not required that f and g are called together, etc.
Back to your example, the following two sub-steps are unsequenced relative to each other:
writing the new value to m, as part of ++m
reading m, as part of --m
When there are two unsequenced operations on the same variable (and at least one of them is a write), it is undefined behaviour which means anything can happen (including unexpected results).
This:
n=++m*--m;
is bad code. Replace it with something clear, such as:
n = (m + 1) * (m - 1);
The original code, for complicated reasons, may not do what you expect, so it's better not to write such code in the first place. If you want to know more about the nitty gritty details of why this is, see here: Undefined behavior and sequence points
++m means "increment m then use its value" The current call with have (m + 1) as value.
m-- means "use the value of m, then decrement it" The current call with have the original value of m, and subsequent calls will have (m - 1) as value
If that makes it any clearer for you, you can also rewrite it as:
int m = 4, n;
n = (m = (m + 1)) * (m = (m - 1));
I am pretty positive the operation occurs before the increment. That is why that is happening. If you break it down like this, it should work.
The answer should be 15 because 4 + 1 is 5 and 4 - 3 is 3, thus 5 * 3 is 15. See below
int main()
{
int m = 4, n;
int g;
n = (m+1) * (m-1);
std::cout << "m=" << m << " and n=" << n << "\n" ;
std::cin >> g;
return 0;
}

Why does the expression a = a + b - ( b = a ) give a sequence point warning in c++?

Following is the test code:
int main()
{
int a = 3;
int b = 4;
a = a + b - (b = a);
cout << "a :" << a << " " << "b :" << b << "\n";
return 0;
}
Compiling this gives the following warning:
> $ g++ -Wall -o test test.cpp test.cpp: In function ‘int main()’:
> test.cpp:11:21: warning: operation on ‘b’ may be undefined
> [-Wsequence-point]
Why can the operation be undefined?
According to my understanding, first the subexpression (b = a) should be evaluated because of higher precedence of (), thus setting b = a. Then, since '+' and '-' have same precedence, the expression would be evaluated left-associatively. Thus, a + b should be evaluated next, and finally the result of (b = a) should be subtracted from a + b. I can't see any sequence-point rule being violated here.
There is a difference between an expression being evaluated and completing its side effects.
The b = a assignment expression will be evaluated ahead of subtraction due to higher precedence of the parentheses. It will provide the value of a as the result of the evaluation. The writing of that value into b, however, may not complete until the next sequence point, which in this case is the end of the full expression. The end result of the overall expression is therefore undefined, because the subtraction may take the value of b before or after the assignment.
In C++, subexpressions in arithmetic expressions do not have temporal ordering.
a = x + y;
Is x evaluated first, or y? The compiler can choose either, or it can choose something completely different. The order of evaluation is not the same thing as operator precedence: operator precedence is strictly defined, and order of evaluation is only defined to the granularity that your program has sequence points.
In fact, on some architectures it is possible to emit code that evaluates both x and y at the same time -- for example, VLIW architectures.
To solve it separate them in two different statements.
PS: Don't forget that humans may make mistakes performing arithmetic operations. Therefore is better to make the operations clearer by separating them in different statements. I hope I helped.
int main()
{
int a = 3;
int b = 4;
/* Two different Statements*/
b = a;
/* or a = a + b - a */
a = a + b - b;
cout<<"a :"<<a<<" "<<"b :"<<b<<"\n";
return 0;
}
a = b + a - a;
is just written as
a = b + a - (b = a)------>> (exp 1)
The following three results same as (exp 1)
a = (b + a - (b = a));
a = ((b + a) - (b = a));
a = (b + a) - (b = a);
Observations
+, - operators has got same precedence and also left to right associativity
Hence 'b+a' gets executed first and then 'a' value gets assigned to 'b' before subtraction
Now observe the following
When a = 10 and b = 20;
a = (b = a) - b + a; =======> a = 10; b = 10
a = ((b = a) - b + a); =======> a = 10; b = 10
a = ((b = a) - (b + a)); =======> a = -10; b = 10
From the above expressions its clear that even if innermost parenthesis gets executed first the associativity is followed first and then the precedence
Note:
To avoid confusion between the precedence of outer and inner parenthesis
Consider the following expression
a = (b + a - (b = a)) =====> Actual Result => a = 20, b = 10;
would have been a = 10, b = 10; (if precedence is primary when compared to associativity)
Thus by the above example we can say that associativity is primary when compared to precedence

C++ Multi-Assign Python feature

I am trying to learn C++. While experimenting, I typed in the following code, not expecting it to work, but hoping it would:
int one = 1, two = 2;
one, two = two, one;
cout << "one = " << one << "\n";
cout << "two = " << two << "\n";
I was encouraged by the fact that the compiler didn't complain, because this is one of the main features that I love about python that most every programming language I've ever learned does not match - the ability to evaluate multiple expressions before assigning the results WITHOUT using a temporary variable. However, I found when I ran it that this code seems to be ineffectual.
After playing around a bit, I discovered that the variable two is actually being set - so, if I ran this code:
one, two = 3, 4;
two would be equal to 3, but one would be unchanged. And so my question is, what exactly is the compiler doing in this statement? I can't for the life of me figure it out.
Thanks,
Brandon
Multi-assignment python style is not supported in C++, the comma operator does not do what you intend: http://en.wikipedia.org/wiki/Comma_operator
If you were assigning the same value to both one and two then you could do
one = two = 3;
but in your case you are not so they must be on separate lines:
one = 3;
two = 4;
if you wanted to swap the values then you must use a temporary third variable:
int temp = one;
one = two;
two = temp;
If we consider the following:
one, two = 3, 4;
the simple case is 3 ,4; here the 4 will be discarded so only 3 will remain, you then have
one, two = 3;
Now you have the assignment operator = which has higher precedence than the , operator so irrespective of what happens with one, two the two = 3; is evaluated first before one, two resulting in:
two = 3;
First, = operator has higher precedence than , thus both lines below are equivalent:
(one), (two = 3), (4);
one, two = 3, 4;
Second, the comma operator is a way to group multiple statements, but only express the value of the last one, so:
int a, b;
a = (b = 5, b*b);
cout << a << '\n';
Would print 25. Hope to have enlightened you on what the compiler was doing.
In C++11 there is std::tie.
Example:
#include <tuple>
#include <iostream>
int main()
{
int a, b;
std::tie(a, b) = std::make_tuple(1, 2);
std::cout << a << ", " << b;
}
Output: 1, 2. std::tie() creates tuple of references - and std::tuple has overload for operator=().
I know it's not same syntax as the one used in Python, but it's functionally the same and you may want to use it.