Undefined behaviour of sub-expressions - c++

Does this result in undefined behaviour because the order of evaluation will be unspecified?
int i = 0, j = 0, k = 0;
int result = i++ + ++j + k++;

No, the result of the evaluation doesn't depend on the unspecified order of evaluation of the sub-expressions.
Undefined behavior only occurs in this situation if two side effects that affect the same object are unsequenced relative to each other or a side effect and a value computation of the same object are unsequenced. The side-effect and value computation of both prefix and postfix increment are explicitly sequenced.

The order of evaluation is unspecified, but who cares? Each operand acts on a completely distinct object. Nothing undefined here.

No, the behavior is perfectly well-defined: j is incremented, then addition is performed, then i and k are incremented. The only thing that is unspecified is the order in which the increments on i and k are performed. The postcondition is i==1, j==1, k==1, result==1.

The rule is that the results are unspecified if you modify a variable more than once. You haven't done that in your example.

It's fine here because you don't use the same variable twice.
What you have is equivalent to:
int i = 0, j = 0, k = 0;
++j;
int result = i + j + k;
++i;
++k;
If you were to have instead int result = i++ + ++i + i++; then you'd have a problem because the order of the increments is unspecified, and you depend on that order.

Here result will be always 1. The values of j, k, and i will be all 1. Also, note that separator for several variable declaration is ,, and not ;:
int i=0, j=0, k=0;

No, it's a classic/well known c++ sequence point issue, see link here for much more detail
http://en.wikipedia.org/wiki/Sequence_point

Here:
int result = i++ + ++j + k++;
Is Equivalent too:
<SP>
(a1)int t1 = i; // i++ part one: The result of post-increment is the original value
(a2) i = i + 1; // i++ part two: the increment part separated from the result
(b1) j = j + 1;
(b2)int t2 = j; // The result of pre-increment is the new value
(c1)int t3 = k; // k++ part one: The result of post-increment is the original value
(c2) k = k + 1;
(d) int t4 = t1 + t2;
(e) int t5 = t3 + t4;
(f) int result = t5;
<SP>
The constraints are:
(a1) is before (a2)
(a1) is before (d)
(b1) is before (b2)
(b2) is before (d)
(c1) is before (c2)
(c1) is before (e)
(d) is before (e)
(e) is before (f)
As long as the above constraints are maintained the instructions can be re-ordered as much as the compiler likes. But the constraints guarantee that the result is well formed.

Related

Why is incrementing and assigning to a reference, not change the value?

I am not able to understand, why the output of the code is not what I was expecting.
#include <iostream>
using namespace std;
int main()
{
int m = 2, n = 6;
int &x = m;
int &y = n;
m = x++;
x = m++;
n = y++;
y = n++;
cout<< m << " " << n;
return 0;
}
I was expecting 4 8
This line:
m = x++;
is equivalent to:
x = x++;
since m is a reference to x.
From c++17, the right hand side is evaluated first, resulting in 2. Then x is incremented to 3. Then the assignment of the right hand side value to the left hand side is done. But this uses the old value of the right hand side, which is 2. So the above statement effectively does nothing.
Before c++17,
m = x++;
is undefined behavior.
Notice how the operators are post-increment and not pre-increment... You're basically doing nothing.
m = x++; means that increment x (i.e. m) but return the old value of x (i.e. m). Assignment takes place after the increment and return of old value and the old value is what ends up getting assigned. So, you end up essentially with a bunch of self-assignments.

Not able to understand the working of Pre-increment/ Pre-decrement in C++

Can someone please explain what is happening in the following code? (Taken from GeeksForGeeks)
int main(){
int a = 10;
++a = 20; // works
printf("a = %d", a);
getchar();
return 0;
}
What exactly is happening when the statement ++a = 20 is executed? Also, please clarify why this code fails in execution?
int main(){
int a = 10;
a++ = 20; // error
printf("a = %d", a);
getchar();
return 0;
}
Code Taken From: http://www.geeksforgeeks.org/g-fact-40/
When you do
++a = 20;
it's roughly equivalent to
a = a + 1;
a = 20;
But when you do
a++ = 20;
it's roughly equivalent to
int temp = a;
a = a + 1;
temp = 20;
But the variable temp doesn't really exist. The result of a++ is something called an rvalue and those can't be assigned to. Rvalues are supposed to be on the right hand side of an assignment, not left hand side. (That's basically what the l and r in lvalue and rvalue comes from.)
See e.g. this values category reference for more information about lvalues and rvalues.
This is the difference between r and l values. If you would have compiled the 2nd code snippet with gcc you would have seen this:
lvalue required as left operand of assignment
meaning, that a++ is rvalue and not a lvalue as it should be if you want to assign something to it
int main(){
int a = 10;
++a = 20; // works
printf("a = %d", a);
getchar();
return 0;
}
This is a c Language.
Explaining Line by line
int main() THIS line define an entry function called main which is expected to return a type integer(int)
int a = 10 declares a variable integer whose value is 10;
++a = 20; AT this point your code is incrementing the value of a by 1 before any operation is performed on a.
This means that, the value of a is incremented by 1 bfore a is assign the value of 20;....
the statement ++a = 20 is incorect in the sense that, a is 10 initially, and you increment it to 11 . Is like saying 11 = 20; this may not throw an error because the code line is not useful.
printf() is a c-method to print file to screen, passing a string "a = %d" tells the compiler to print a to a decimal number(%d).
getchar() is use to terminate the running program and return 0 is to forcefully tell the operating system that the code run successfully and return integer value 0.
int main(){
int a = 10;
a++ = 20; // error
printf("a = %d", a);
getchar();
return 0;
}
This didn't at a++ = 20 because , right value increment perform the operation before it increment unlike ++a who increment before performing operation.
So this isn't possible and it never works because a is already 10, and you are saying the value ++ and assign 20, you can't assign a value to it, it should be the one calculating its own value. So the compiler will want to interprete is as variable a++ = 20, and ++ can not be a vaiable name. That's why it never work.
What is the essence of incrementation and decrementation in c....its useful for creating conditional statement e.g for loop, while statement etc. for example:
for(int i = 0; i < 4; i++)
{
printf('THis is c-language');
}
or
int i = 0;
while(i < 4){
printf('THis is c-Language');
i++;
}
so therefore, following the programming rules and regulations, you are not allow to assign value to either a++ or ++a
they are for the compilers to manipulate, so never assign value to them.
Thank you.
The left operand of the assignment operator should be an lvalue.
The expression ++a is an lvalue while a++ is not and therefore it can't be the left operand of the assignment operator.
n3797-ยง 5.3.3(p1):
[...] The result is the updated operand; it is an lvalue [...]

Adding `bool` to `float`

I'm maintaining some code and came across this snippet:
int num = 0;
float sum = 0.0;
bool value[rows][cols]; //initialized elsewhere in the code
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
if(value[i][j] == true) {
sum += value[i][j]; //shouldn't this be equivalent to "sum += 1;"
//as it is in the if block?
num++;
}
float ans = 1.0;
if(num > 12)
ans = sum / num;
Is the guy who wrote this code originally doing something fiendishly clever here, or should ans always be 1? As far as I can tell, num and sum should always be exactly the same value, no?
This will the same as sum += 1 since a true value will be converted to 1 this is covered in the draft C++ standard section 4.9 Floating-integral conversions which says:
If the source type is bool, the value
false is converted to zero and the value true is converted to one.
The additive operators will cause the usual arithmetic conversions to be performed on their operands. Which in this case will be covered by this case:
Otherwise, if either operand is float, the other shall be converted to float.
and we know that E1 += E2 is equivalent to E1 = E1 + E2 from section 5.17 Assignment and compound assignment operators which says:
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is
evaluated only once.[...]
The answer is not fiendlishly clever because the if statement is still present.
To be clever, one would do something like this:
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
sum += value[i][j]; // Add 1 if true, 0 if false.
num += value[i][j]; // Add 1 (increment) if true, add 0 if false
}
}
The assumption is that a bool type will convert to 1 if true, and 0 if false. This is how things were done in the dawn of computers.
If the true evaluates to some nonzero value other than 1, this code will not work correctly.
Upon further analysis, the sum and num will have the same value at the end of the loops.
So, only use num and convert to float at the end of the loop.
If value is a (two-dimensional) array of bool, then this is equivalent with sum += 1. In contrast with what some people think, a comparison with == true is not the same as an implicit conversion to bool (e. g. in the context of an if statement's condition). Any integer not equal to 1 will be considered different from true.

Preincrement and Postincrement

I've been trying to understand how post and pre increments work lately and I've been over thinking it too much.
Does "Product" become 25 after one iteration?
Product *=5++
And does "Quotient" become 5/6 after one iteration?
Quotient /= ++x
5++ is just incorrect.
Quotient /= ++x; is the same as x = x + 1; Quotient = Quotient / x; (assuming these are just plain numbers).
Your code isn't valid C++, since the built-in post-increment operator may only be applied to lvalues, but literal integers are rvalues.
Beside that, the value of a (built-in) pre-increment expression is the incremented value, while the value of a post-increment expression is the original value.
Pre-increment modifies the variable and evaluates to the modified value.
Post-increment evaluates to the value of the variable and then increments the variable.
int a = 5;
int b = ++a; // a = a + 1; b = a
int c = a++; // c = a; a = a + 1
Consider these simple implementations of ++ for int
int& int::preincrement()
{
this->m_value += 1;
return *this;
}
int int::postincrement()
{
int before = this->m_value;
this->m_value += 1;
return before;
}

Increment, preincrement and postincrement

Help me to resolve this please. The steps that follows that expressions are:
//Expression
offSpring1[m1++] = temp1;
//Steps:
1.- increment m1
2.- assign temp1 to offSpring
I have always thought that the expression inside the brackets was the first to be done. But now I am confuse. So if a write this:
//Expression
offSpring1[++m1] = temp1;
//Steps would be:
1.- assign temp1 to offSpring
2.- increment m1
If the steps would be the same as first ones, what is the difference between i++ and ++i?
int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;
output:
0
1
reset
1
1
i++ returns the value as it currently stands in the expression, then increments the variable.
++i will increment the variable, then return the value to use in the current expression.
offSpring1[m1++] = temp1;
is
offSpring1[m1] = temp1;
m1 += 1;
and
offSpring1[++m1] = temp1;
is
m1 += 1;
offSpring1[m1] = temp1;
j = ++i is the same as i = i+1; j = i;
j = i++ is the same as j = i; i = i+1;
Just run these two different test programs to understand the difference between the post-increment and the pre-increment operators
For ++i (pre-increment)
int main()
{
int* offSpring = calloc(20,sizeof(int));
int m1 =1;
offSpring[++m1] = 10;
printf("%d,%d",offSpring[m1],m1);
}
In the first one you will get 10 as the value of offSpring[m1].
Why? Because this is the pre-increment operator which means that first m1 gets incremented and the the rest gets evaluated.
For i++(post-increment)
int main()
{
int* offSpring = calloc(20,sizeof(int));
int m1 =1;
offSpring[m1++] = 10;
printf("%d,%d",offSpring[m1],m1);
}
In the second because the post-increment operator is used you will get a 0 value since you are first assigning 10 to offSpring[m1] and then m1 gets incremented.
offSpring1[m1++] = temp1; doesn't do what you said.
assign temp_m1 = m1.
increment m1.
index offSpring1[temp_m1]
assign temp1 into indexed value.
On the other hand offSpring1[++m1] = temp1; works like this:
increment m1.
index offSpring1[m1]
assign temp1 into indexed value.
Even though postfix increment is the first to be evaluated in your first example, its value is the original value of the variable being incremented.
offSpring1[m1++] = temp1;
So even though m1 is incremented before array idexing, the value of temp1 is assigned at position m1 - 1.
There are two aspects to an expression (or sub-expression): its value,
and its side effects. The value of i ++ is the value of i; the
value of ++ i is the value i + 1, converted to the type of i.
This is the value used in the expression. The side effects of both is
to increment the variable i. This may occur at any time after the
preceding sequence point and before the next. Supposing i is a global
variable, and you write something like:
i = 0;
f()[i ++] = g();
f()[++ i] = g();
The standard says nothing about whether the value of i seen in f()
or g() is that before the incrementation, or after. In neither case.
All the standard says is that the effects of the incrementation will
take place after the start of the full expression (but perhaps as the
first thing in the full expression) and before the end of it. (And that
they won't be interleaved with a function call, so that if f()
reads i twice, it is guaranteed to see the same value.)
Unfortunately, in those 2 code snippets you've posted there, there's no guaranteed order of evaluation. If your expressions are inappropriate, more or less anything could happen.
To start with the difference between a++ and ++a:
a++ will increment a but the expression using it will see the value of a before the increment
++a will increment a, and the expression using it will see the incremented value.
List item
with
buffer[a++] = b;
the compiler can decide to do the ++ at any point within the expression. Thus if 'b' is actually an expression involving a, you can get different results on different compilers. Both of the following would be valid:
get the value of a;
increment a
work out where buffer[old value] points to
evaluate b
store b
or this
evaluate b;
work out where buffer[a] points to
store b
increment a
if 'b' should happen to involve a, those 2 implementations would produce different results. Both are valid.
It works precisely the opposite of what you described:
offSpring1[m1++] = temp1 is the same as
offSpring[m1] = temp1; m1 = m1 + 1;
OffSpring1[++m1] = temp1 is the same as
m1 = m1 + 1; OffSpring1[m1] = temp1;
Prefix notation increments before evaluating the expression
Postfix notation increments after evaluating the expression
The description of the first is the correct description for the second. The correct description of the first is very similar, you just need a "copy current value of m1" step added before the others.
But you do have a distinct lack of sequence points here, if m1 has a primitive type. The rules change somewhat between C++03 and C++11.
If m1 has a user-defined type, then there are function calls involved which influence sequencing.
This code
offSpring1[m1++] = temp1;
performs the following (if m1 is a primitive type):
auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }
This code
offSpring1[++m1] = temp1;
is exactly the same except that lhs is bound using new_m1 instead of old_m1.
In either case, it is unspecified whether lhs is written to before or after m1.
If m1 is not a primitive type, it looks more like:
auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;
vs
auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;
In both these cases, the change to m1 is definitely made before the write to lhs.