Is using an assignment operator in a function argument undefined behaviour? - c++

I found some code similar to this in an example my university tutor wrote.
int main(){
int a=3;
int b=5;
std::vector<int>arr;
arr.push_back(a*=b);
std::cout<<arr[0]<<std::endl;
}
Is there a well-defined behaviour for this? Would arr[0] be 3 or 15 (or something else entirely)?
Visual Studio outputs 15, but I have no idea if that's how other compilers would respond to it.

Before push_back is executed, the expression passed as argument will need to be computed. So what is the value of a *= b. Well it will always be a * b and also the new value of a will be set to that one.

It's valid and works as you expect.
The expression is first evaluated and the result is "returned".
auto& temp = (a*=b);
arr.push_back(temp);

The value of an expression with the compound assignment operator is the value of the left operand after the assignment.
So the code your showed is valid. Moreover in C++ (opposite to C) the result is an lvalue. So you may even write :)
arr.push_back( ++( a *= b ) );
In this case the next statement outputs 16.:)

Related

What's the difference in following code, when I use parentheses I get expected result but random number if I don't use the parentheses

Program 1:
#include <iostream>
using namespace std;
int main(){
int x=5;
int* xd=&x;
cout<<*xd<<endl;
(*xd)++;
cout<<*xd;
}
output is 5 and 6 .
Program 2:
#include<iostream>
using namespace std;
int main(){
int x=5;
int* xd=&x;
cout<<*xd<<endl;
*xd++;
cout<<*xd;
}
Output is 5 and some random number rather than 6.
The second code uses *xd++; which is equivalent to *(xd++); due to operator precedence. In other words, the postfix operator++ has higher precedence than operator * used for indirection and thus by writing *xd++ you're incrementing the pointer xd and then dereferencing that incremented pointer in the next statement cout<<*xd; which leads to undefined behavior.
cout<<*xd;//undefined behavior as this dereferences the incremented pointer
While the first code is well-formed because in code 1, you're first dereferencing the pointer xd and then incrementing that result(which is an int) which is totally fine.
(*xd)++; //valid as you've surrounded xd with parenthesis () and thus you're incrementing x instead of xd
cout<<*xd;//valid as `xd` still points to `x`
For the first lines of code you wrote :
int main(){
int x=5; // Here x is equal to 5
int* xd=&x; // You declare a pointer xd that points on the value of x
cout<<*xd<<endl; // The value of xd is 5.
(*xd)++; // The value of 5 +1 which is equal to 6
cout<<*xd; // Print out 6
As for the second code
include using namespace std;
int main(){
int x=5; // Here x is equal to 5
int* xd=&x; // You declare a pointer xd that points on the value of x
cout<<*xd<<endl; // The value of xd is 5.
*xd++; // increment the value of the pointer address by 1
cout<<*xd; // Display a random pointer address
}
To understand more, you should learn about the pointer address and the pointer value
Doing (*xd)++ will increment the value of your pointer.
As for *xd ++ will increment a random value that your pointer address is pointing on.
In the first example, the increment operator is being performed on the dereferenced value of xd (i.e. 5+1).
In the second example, the incprement operator is being performed on the pointer to the memory address where 5 is held, i.e. moving the pointer to after the value (which is not initialized)
I've Got the right answer to that Question.
Actually some operators have the same precedence, like '*' and '++'. So if they're found in the same statement the compiler deals them with associativity .
Associativity is concerned with whether the compiler performs operations starting with an operator on the right or an operator on the left.
If a group of operators has right associativity, the compiler performs the operation on the right side of the expression first, then works its way to the left. The unary operators such as * and ++ have right associativity, so the expression from the 2nd code is interpreted as *(xd++), which increments the pointer first, not what it points to. Since I've used parentheses in first code which means to deference the pointer first (*xd) ... then whatever value it holds..... increment it.
THANK YOU !

lvalue required as left operand of assignment error when using C++

int main()
{
int x[3]={4,5,6};
int *p=x;
p +1=p;/*compiler shows error saying
lvalue required as left
operand of assignment*/
cout<<p 1;
getch();
}
When you have an assignment operator in a statement, the LHS of the operator must be something the language calls an lvalue. If the LHS of the operator does not evaluate to an lvalue, the value from the RHS cannot be assigned to the LHS.
You cannot use:
10 = 20;
since 10 does not evaluate to an lvalue.
You can use:
int i;
i = 20;
since i does evaluate to an lvalue.
You cannot use:
int i;
i + 1 = 20;
since i + 1 does not evaluate to an lvalue.
In your case, p + 1 does not evaluate to an lavalue. Hence, you cannot use
p + 1 = p;
Put simply, an lvalue is something that can appear on the left-hand side of an assignment, typically a variable or array element.
So if you define int *p, then p is an lvalue. p+1, which is a valid expression, is not an lvalue.
If you're trying to add 1 to p, the correct syntax is:
p = p + 1;
To assign, you should use p=p+1; instead of p+1=p;
int main()
{
int x[3]={4,5,6};
int *p=x;
p=p+1; /*You just needed to switch the terms around*/
cout<<p<<endl;
getch();
}
if you use an assignment operator but use it in wrong way or in wrong place,
then you'll get this types of errors!
suppose if you type:
p+1=p; you will get the error!!
you will get the same error for this:
if(ch>='a' && ch='z')
as you see can see that I i tried to assign in if() statement!!!
how silly I am!!! right??
ha ha
actually i forgot to give less then(<) sign
if(ch>='a' && ch<='z')
and got the error!!
It is just a typo(I guess)-
p+=1;
instead of p +1=p; is required .
As name suggest lvalue expression should be left-hand operand of the assignment operator.

the increment of a returned value

I have defined a function like this:
int test(int n) {
const int b = n;
return b;
}
While in the main function, I use like this:
int temp = test(50)++;
And the g++ reports an error:
error: lvalue required as increment operand
Actually, I'm fully confused by this. Would you like to give me some tips or explain it to me.
You can only apply ++ to an lvalue (at least of built-in type). The return value from a function can be an lvalue if if it returns a reference, but otherwise it's an rvalue (in which case, you can't apply ++ to it).
The value returned from test is an rvalue. You cannot use the increment operator (++) on it. You can change your calling code to:
int temp = test(50);
temp++;
or
int temp = test(50) + 1;
Once constant value get intialised you cant not change that value.So its giving error try to execute same function without increamenting const value.
'plusplus' operator is (almost) equivalent to '+= 1' that is 'assign the variable its previous value incremented by one'. The value returned is not a variable, so it can not be the left-side argument of an assignment. That's why the increment operator is not applicable here. Just do
t = test(50) + 1;
or
t = test(50);
t ++;

Decrement Operator in C++

I am from C background, and now I am learning OOP using C++
Below is a program that calculates factorial.
#include <iostream>
using namespace std;
void main ()
{
char dummy;
_int16 numb;
cout << "Enter a number: ";
cin >> numb;
double facto(_int16);
cout << "factorial = " <<facto(numb);
cin >> dummy;
}
double facto( _int16 n )
{
if ( n>1 )
return ( n*facto(n-1) );
else
return 1;
}
The above code works fine.
But if I replace the return statement
return ( n*facto(n-1) );
with this
return ( n*facto(n--) );
then it doesn't work. The n-- won't decrement n by 1. Why?
I am using Visual Studio 2012
Edit:Got it! thanks :)
*also, I would like to add to the answers below: using --n will cause the n to decrement before the statement is executed. So, due to pre-decrement, the expression will become (n-1)*facto(n-1) . That is why it is better not to use pre-decrement in this case *
Currently, by using n-- you are passing the original and therefore unmodified value of n into facto which is causing a loop.
You need to use n - 1 instead. It would, on the face of it, be tempting to use --n since that would decrement n and evaluate to the new (lower) value. But --n will give you undefined behaviour since you are pre-multiplying the function return value by n and since * is not a sequence point, the value of n is not well-defined.
(By the way, the behaviour in C would have been identical).
[Edit: acknowledge Mike Seymour on the undefined behaviour point].
EDIT:: The explanation below is only to shed light on the usage of Post and Pre-Decrement for OP's better understanding of them. The correct answer for OP's code is, n*facto(n - 1). #OP: You should not do any pre-drecrement in that part of your code because it will invoke Undefined Behavior due to unsequenced modification of variable n.
Pre And Post-Decrement::
You have to use pre-decrement (wiki-link) if you want to decrement the variable before the value is passed. On the other hand, a post-decrement evaluates the expression before the variable is decremented:
int n = 10, x;
x = --n; // both are 9
and
int n = 10, x;
x = n--; // x = 10, i = 9
Why not to use pre-decrement in your case?:: n*facto(n--) causes UB.
Why?
The Standard in ยง5/4 says
Between the previous and next sequence point a scalar object shall
have its stored value modified at most once by the evaluation of an
expression.
and
The prior value shall be accessed only to determine the value to be
stored.
It means, that between two sequence points a variable must not be modified more than once and, if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.
return ( n*facto(n--) );
You are using the post decrement operator.
What happens is, You pass the value of n to the function and then decrement it. That doesn't affect the value that is already passed to the function

C/C++ comma operator puzzles me. Language lawyers?

I came across this bit of code in an example from the Boost documentation:
std::vector<int> input;
input += 1,2,3,4,5,6,7,8,9;
How cute. Boost has a template for operator+= that takes advantage of the fact that the comma is, under most circumstances, an operator. (Wisely, C++ does not allow a hackist to overload "operator,".)
I like to write cute code too, so I played around some with the comma-operator. I found something that looks weird to me. What do you think the following code will print?
#include <iostream>
int main() {
int i;
i = 1,2;
std::cout << i << ' ';
i = (1,2);
std::cout << i << std::endl;
}
You guessed it. VC++ 2012 prints "1, 2". What's up with that?
[Edit: I should have been more precise. Should have said C++ does not allow operator "," in a list of int's to be overloaded. Or better yet, nothing. The ',' operator can be overloaded for classes and enums.]
CASE 1:
i = 1,2;
= has higher precedence than ,
hence, 1 is assigned to i.
Since assignment evaluates to an lvalue in c++,(evaluates to rvalue in c) it becomes i,2 which evaluates to2 (refer NOTE)
CASE 2:
i = (1,2);
() has higher precedence than =
expressions or operands separated by , operator evaluates to the value of the last expression or operand hence, 2 is assigned to i
NOTE
a comma expression like 33,77,x,y,z is evaluated from left to right.
The result of such comma expression is the value of rightmost expression .
Examples
Consider, int z=100;
then
1,4,5; //evaluates to 5
1,100,z+100; //evaluates to 200
Simple: "=" has higher precendence.
i = 1,2;
Is like (i=1),2, meaning the result of the expression is 2 but it's discarded.
i = (1,2);
The result of (1,2) is 2.
EDIT: this might be so things like
for (i=0, j=0; ...)
work as expected.