How should i read an assignment? - c++

I'm studying C++ as a beginner and my book explain me what is assignment but i can't understand a little concept that the book is trying to make me understand:
int a = 3; // a starts out with the value 3
a = a + 7; // a gets the value of a + 7 (that is, 10)
What my book says is: the last assignment deserves notice.First of all it clearly shows that = doesn't mean equals-clearly, a doesn't equal to a + 7.It means assignment, that is, to place a new value in a variable. What does it mean ? how should i read an assignment?
For example:
a = a + 7; // should i read it as: a is equal to a + 7 ?

The code might be expanded in following way:
int a; // declaration of the variable. a has undefined value.
a = 3; // Assign the value 3 to a. a is 3.
a = a + 7; // Assign value of (a + 7) to a. a is 10.
The expression (a + 7) is evaluated first and the value of (3 + 7) is assigned to a.
The token = is used for assignment and doesn't have anything to do with equality.

The assignment means that the right-hand side (rhs) will be evaluated to a single value, then assigned to the left-hand side (lhs)
a = a + 7;
Now, rhs --> a + 7 --> 3 + 7 --> 10, now we have a single value, and will assign 10 to a

In C++ = is the assignment operator. == is the equality operator.
Read the chapter about operator precence (the order in which operators performs operations on its operands).
= (the assignment operator) is a binary operator, has lowest precedence (that is the reason first a+7 operation is performed) and it assigns the result of an expression on its right side to the variable on its left side.
For, a = a + 7, never read it as a equals a + 7, but make habit of reading it as a gets assigned the value of a + 7 (or whatever the expression) is.
The = also replaces the exiting value of variable on left side (a) with the result of expression on right side ( a + 7).

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).

What does "expression must be a modifiable lvalue" mean?

int x;
(rand() % 100) + 1 = x;
It keeps saying:
expression should be a modifiable lvalue
Left and right operands of = are not interchangable.
It's the left operand that's being assigned to, so it has to be assignable.
Given int x;, x is assignable (a 'modifiable lvalue'), but x + 42 is not (an rvalue).
It means that you've put the wrong things on each side of the assignment operator (=). The expression on the left should be something you can assign a value to (the "l" in "lvalue" stands for "left"), and the expression on the right should compute the value you want to assign.
Try
x = (rand() % 100) + 1;
instead.
The lvalue always has to be a changeable/modifiable one.
So you can't do :
int a ;
3 = a ;
This means that you are trying to change 3 to a which is not possible because 3 is a constant.
So similarily,
Do this :
x = (rand() % 100) + 1;
And, the error should be gone.

Comma operator used in assignment

Consider the code:
int i, j;
i = (i = 1, j = 3);
i++;
cout<<i<<" "<<j;
This printed 4 3 (c++14).
I read that the comma operator evaluates the expression on its left and returns the one on its right. Now if that is correct, I want to know what is the return value of j = 3? Is it the rvalue? Or a reference to the lvalue?
How does this actually work?
I want to know what is the return value of j = 3?
Assignment operations* return (or "evaluate to") a reference to the left-hand side of the operation, in this case j.
So i = (i = 1, j = 3); is identical to:
i = 1;
j = 3;
i = j;
*For built-in types that is. Custom operator= overloads may return whatever they want, although it's recommended to return a reference to *this as it is the expected behavior among C++ programmers.
To calculate (i=1, j=3), it calculates, from left to right, the expressions separated by comma, and returns the value of the last (rightmost) expression. So it calculates i=1 (i becomes 1), then it calculates j=3 (j becomes 3), then returns 3.
After calculating (i=1, j=3), which returned 3, it performs the assignment, which sets i to 3.
Then i++ is calculated, which sets i to 4.
Then i and j are printed.
The assignment operator returns an lvalue referring to the left operand. It groups right-to-left. ([expr.ass]). Note that saying returning a reference to the lvalue doesn't make sense - it either returns an lvalue or not.
The comma operator performs the value computations and side effects from the left operand, discards them, and then does the same for the right operand. ([expr.comma])
So refactoring the comma operator would produce the following equivalent code:
i = 1; // left operand, value discarded
i = j = 3; // right operand, value preserved
i++;
and then refactoring the compound assignment would produce the following still equivalent code:
i = 1;
j = 3; // rightmost assignment
i = j; // leftmost assignment
i++;

What's going under the hood in this simple C++ code?

#include<iostream>
int main()
{
int a = 5;
a = (a = 10, a++, a--);
std::cout << a;
}
Output is 11,
But when I modify the line
a = a=10,a++,a--;
Output is 10
What effect does removing the ( ) operator has and in what order the operators are being executed.
The + and - operators take precedence before the assignment operator and the +,- signs are read by the compiler from left to right, whereas the assignment operators are read by the compiler from right to left. So:
1) a++
2) a--
3) a=10
4) a =
The c++ compiler will pass your complete set code to a binary tree which will rearrange your code according to the precedence of the operator = + - etc in left node or right node

Operator Precedence

I have a sample midterm question that I am not too sure about. Here it is:
#include <iostream.h>
void f( int i )
{
if( i = 4 || i = 5 ) return;
cout << "hello world\n" ;
}
int main()
{
f( 3 );
f( 4 );
f( 5 );
return 0;
}
So I understand that the logical OR operator has a higher precedence and that it is read left to right. I also understand that what's being used is an assignment operator instead of the relational operator. I just dont get how to make sense of it all. The first thing the compiler would check would be 4 || i? How is that evaluated and what happens after that?
Let's add all the implied parentheses (remembering that || has higher precedence than = and that = is right-associative):
i = ((4 || i) = 5)
So, it first evaluates 4 || i, which evaluates to true (actually, it even ignores i, since 4 is true and || short-circuits). It then tries to assign 5 to this, which errors out.
As written, the code doesn't compile, since operator precedence means it's i = ((4 || i) = 5) or something, and you can't assign to a temporary value like (4 || i).
If the operations are supposed to be assignment = rather than comparison == for some reason, and the assignment expressions are supposed to be the operands of ||, then you'd need parentheses
(i = 4) || (i = 5)
As you say, the result of i=4 is 4 (or, more exactly, an lvalue referring to i, which now has the value 4). That's used in a boolean context, so it's converted to bool by comparing it with zero: zero would become false, and any other value becomes true.
Since the first operand of || is true, the second isn't evaluated, and the overall result is true. So i is left with the value 4, then the function returns. The program won't print anything, whatever values you pass to the function.
It would make rather more sense using comparison operations
i == 4 || i == 5
meaning the function would only print something when the argument is neither 4 nor 5; so it would just print once in your example, for f(3).
Note that <iostream.h> hasn't been a standard header for decades. You're being taught an obsolete version of the language, using some extremely dubious code. You should get yourself a good book and stop wasting time on this course.
The compiler shall isuue an error because expression 4 || i is not a lvalue and may not be assigned.
As for the expression itself then the value of it is always equal to true because 4 is not equal to zero.