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;
Related
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.
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;
}
This question already has answers here:
Post-increment and Pre-increment concept?
(14 answers)
Closed 6 years ago.
so I am looking at the following snippet of code
int a = 3;
int b = 2;
b = a++;
cout << ++b;
My understanding line by line is:
initiate a = 3
initiate b = 2;
assign the value of (a+1) to b, so b = 4;
print b+1, which is 5.
However this is wrong, can someone explain this in simple terms? I am new to C++
In the statement:
b = a++
a is evaluated for the assignment to b and after that a is then incremented so a = a+1.
On the other hand:
b = ++a
Increments a so a = a+1 before a is then evaluated for assignment to b.
You can look deeply here:
Pre-increment or post-increment in C/C++
In C++ when an increment or decrement is used in an expression, the position of "++" or "--" matters.
If the operator is before a variable then the increment or decrement will be done before the end of the expression, in the opposite situation the increment or decrement will be done after the entire expression is executed.
int b = ++a; // first add +1 to a, then assign a to b
int b = a++; // assign a to b, then add +1 to a
Here you go:
initiate a = 3
initiate b = 2;
assign the value of (a) to b, so b = 3 and increment a to 4;
print b+1, which is 4.
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
Is there a c++ operator that i could use for a for loop where it would add or subtract to variables based on whether one of the variables is less than or greater 0.
For instance
int a;
int b;
for(int i=0;i<some_number; i++)
result = a +< b
result = a-> b
No.
You can combine with the ?: operator.
int a;
int b;
for(int i=0;i<some_number; i++)
result = (a < b)? result+b:result-b;
That is if I understood your example correctly.
-> is an existing dereference operator.
Operator ?: is an equivalent to the if...else construct. If the statement before ? evaluates to true, the statement right after the ? gets executed, otherwise the statement after the : gets executed.
Do you want something like this?
result += a > 0 ? b : -b;
Note that this will subtract b if a == 0, which isn't quite what you asked for.
Not directly, but the ternary operator is close.
for(int i=0;i<some_number; i++)
result = (a > 0)?(a):(b);
This line will be equivalent to result = a when a is greater than 0, and result = b elsewise.
It could also be written as result = a?a:b;, but the longer form is more readable.
Not sure if this would be any help?
result = a + (b*(a < b));
result = a - (b*(a > b));
Basically, (a < b) is converted into a boolean, which is basically either 1 (true) or 0 (false). b multiplied by 0 is of course zero, so nothing is added, and b multiplied by 1 is exactly b's value.