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.
Related
This (note the comma operator):
#include <iostream>
int main() {
int x;
x = 2, 3;
std::cout << x << "\n";
return 0;
}
outputs 2.
However, if you use return with the comma operator, this:
#include <iostream>
int f() { return 2, 3; }
int main() {
int x;
x = f();
std::cout << x << "\n";
return 0;
}
outputs 3.
Why is the comma operator behaving differently with return?
According to the Operator Precedence, comma operator has lower precedence than operator=, so x = 2,3; is equivalent to (x = 2),3;. (Operator precedence determines how operator will be bound to its arguments, tighter or looser than other operators according to their precedences.)
Note the comma expression is (x = 2),3 here, not 2,3. x = 2 is evaluated at first (and its side effects are completed), then the result is discarded, then 3 is evaluated (it does nothing in fact). That's why the value of x is 2. Note that 3 is the result of the whole comma expression (i.e. x = 2,3), it won't be used to assign to x. (Change it to x = (2,3);, x will be assigned with 3.)
For return 2,3;, the comma expression is 2,3, 2 is evaluated then its result is discarded, and then 3 is evaluated and returned as the result of the whole comma expression, which is returned by the return statement later.
Additional informations about Expressions and Statements
An expression is a sequence of operators and their operands, that specifies a computation.
x = 2,3; is expression statement, x = 2,3 is the expression here.
An expression followed by a semicolon is a statement.
Syntax: attr(optional) expression(optional) ; (1)
return 2,3; is jump statement (return statement), 2,3 is the expression here.
Syntax: attr(optional) return expression(optional) ; (1)
The comma (also known as the expression separation) operator is evaluated from left to right. So return 2,3; is equivalent to return 3;.
The evaluation of x = 2,3; is (x = 2), 3; due to operator precedence. Evaluation is still from left to right, and the entire expression has the value 3 with the side-effect of x assuming the value of 2.
This statement:
x = 2,3;
is composed by two expressions:
> x = 2
> 3
Since operator precedence,
= has more precedence than comma ,, so x = 2 is evaluated and after 3. Then x will be equal to 2.
In the return instead:
int f(){ return 2,3; }
The language syntax is :
return <expression>
Note return is not part of expression.
So in that case the two expression will be evaluated will be:
> 2
> 3
But only the second (3) will be returned.
Try to apply the simplistic approach just highlighting the precedence with parenthesis:
( x = 2 ), 3;
return ( 2, 3 );
Now we can see the binary operator "," working in the same way on both, from left to right.
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++;
I read "C++.Primer plus. Stephen Prata"(6th edition).
On page 209 was:
y = (4 + x++) + (6 + x++);
The expression 4 + x++ is not a full
expression, so C++ does not guarantee that x will be incremented
immediately after the subexpression 4 + x++ is evaluated. Here the
full expression is the entire assignment statement, and the semicolon
marks the sequence point, so all that C++ guarantees is that x will
have been incremented twice by the time the program moves to the
following statement. C++ does not specify whether x is incremented
after each subexpression is evaluated or only after all the
expressions have been evaluated, which is why you should avoid
statements of this kind.
And I read "Sequence Points and Expression Evaluation" Visual Systems Journal, August 2002. Klaus Kreft & Angelika Langer.
There was:
x[i]=i++ + 1;
Let's assume variable i has the value 1 before we enter the statement.
What will be the result of evaluation of this expression? The correct
answer is: we don't know. However, programmers ever too often believe
that they know what this program fragment does. Typical answers
include: "x[1] will have the value 2", or "x[2] will have the value
2", or even "x[1] will have the value 3".
The third option is definitely wrong. This will not happen because i++
is a postfix increment and returns i's initial value 1; hence the
value of the right hand side of the assignment is 2, and definitely
not 3. [...] So far so good, but we do not know
which entry of the array x will be modified. Will the index be 1 or 2
when the right hand side value will be assigned to x[i]?
There is no definite answer to this question. It fully depends on the
order in which the compiler evaluates the subexpressions. If the
compiler starts on the right hand side of the assignment and evaluates
i++ + 1 before it figures out which position in the array x must be
assigned to then x[2] will be modified because i will have already
been incremented in the course of evaluating the subexpression i++.
Conversely, if the compiler starts on the left hand side and figures
out that it must assign to position i in array x, which at that time
will still be position 1, before it evaluates the right hand side then
we'll end up with a modification of x[1]. Both outcomes are equally
likely and equally correct. "
How understand where is subexpression?
4 + x++ and 6 + x++ are subexpressions, because they are into round brackets?
x[i] and i++ + 1 are subexpression? Why?
I'm interested in this, because I want to understand where side effect can happened in the hypothesis.
Breaking this down, the line
y = (4 + x++) + (6 + x++);
is an expression-statement. Such a thing consists of an expression followed by a ;, so
y = (4 + x++) + (6 + x++)
is an expression.
Since this expression is not part of another expression (but only of an expression-statement), it is a full-expression. A sub-expression on the other hand is an expression that is part of another expression. In the following, I will use capital letters to name expressions, rather than C++ identifiers.
The full-expression above is an assignment-expression of the form:
y = A
where A is the remaining additive-expression
(4 + x++) + (6 + x++)
An additive expression is of the form X + Y, so we break this down into two expressions
(4 + x++)
(6 + x++)
The first one consists of an expression of the form (Z), where Z is 4 + x++. And 4 + x++ consists of two expressions 4 and x++. And so on. All of these expressions are part of
y = (4 + x++) + (6 + x++)
and hence they are sub-expressions of the above expression.
What can be a subexpression?
Any expression can be a subexpression. Although, some expressions may not be subexpressions of certain other expressions.
4 + x++ and 6 + x++ are subexpressions
Correct. Both of those are arithmetic expressions, additions to be more specific.
because they are into round brackets?
Well, sort of. Being inside parentheses, they are indeed the subexpression of the parenthesized expression.
† In general, they're subexpressions because they're expressions, but are also part of another expression.
x[i] and i++ + 1 are subexpression? Why?
Yes, they are. See †.
Here is a handy list of all possible expressions in c++.
Let's find the subexpressions in y = (4 + x++) + (6 + x++);. The first expression that has no subexpressions is 4. It is a literal. It is a subexpression of 4 + x++ which is an addition. Additions have the form A + B. In this case, subexpression A is 4 an subexpressiond B is x++, which is a post increment. Oh, but that contains a subexpression too: x. It is an identifier, and contains no subexpressions. 4 + x++ is a subexpression of the parenthesized expression (4 + x++). That is a subexpression of (4 + x++) + (6 + x++) which is a subexpression of y = (4 + x++) + (6 + x++); which is an assignment. The assignement is a full-expression - not a subexpression. I left some of the subexpressions unexplored, and I shall leave them as an exercise for the reader.
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).
Its giving me this error for line *(repetitions + x)++; inside this for loop. Any clues why?
for (int y = 0; y<hours; y++)
{
if (*(array + x) == *(array + y))
{
*(repetitions + x)++;
}
}
You can't increment the rvalue repetitions + x. This is the same error as writing:
int a = 3;
int b = 2;
(a+b)++; // ????
The ++ operator requires an lvalue, i.e. the designation of a variable. a+b is a temporary result and doesn't have a memory address, it can't be incremented.
It's possible that you meant to write (*(repetitions + x))++;, which could be more clearly expressed as repetitions[x]++;
This parses as *((repetitions + x)++) -- that is, it tries to modify a constant address, then dereference it. Presumably you intended increment what the address pointed at instead.
You can do that a couple different ways. One would be to use parentheses. Another to use pre-increment:
++*(repetitions + x);
or:
(*(repetitions + x))++;