5.4. Assignment Operators
The left-hand operand of an assignment operator must be a nonconst lvalue. Each of these assignments is illegal:
Array names are nonmodifiable lvalues: An array cannot be the target of an assignment. Both the subscript and dereference operators return lvalues. The result of dereference or subscript, when applied to a nonconst array, can be the left-hand operand of an assignment:
int i, j, ival;
const int ci = i; // ok: initialization not assignment
1024 = ival; // error: literals are rvalues
i + j = ival; // error: arithmetic expressions are rvalues
ci = ival; // error: can't write to ci
The result of an assignment is the left-hand operand; the type of the result is the type of the left-hand operand.The value assigned to the left-hand operand ordinarily is the value that is in the right-hand operand. However, assignments where the types of the left and right operands differ may require conversions that might change the value being assigned. In such cases, the value stored in the left-hand operand might differ from the value of the right-hand operand:
int ia[10];
ia[0] = 0; // ok: subscript is an lvalue
*ia = 0; // ok: dereference also is an lvalue
Both these assignments yield values of type int. In the first case the value stored in ival is the same value as in its right-hand operand. In the second case the value stored in ival is different from the right-hand operand.
ival = 0; // result: type int value 0
ival = 3.14159; // result: type int value 3
5.4.1. Assignment Is Right Associative
Like the subscript and dereference operators, assignment returns an lvalue. As such, we can perform multiple assignments in a single expression, provided that each of the operands being assigned is of the same general type:
Unlike the other binary operators, the assignment operators are right associative. We group an expression with multiple assignment operators from right to left. In this expression, the result of the rightmost assignment (i.e., jval) is assigned to ival. The types of the objects in a multiple assignment either must be the same type or of types that can be converted (Section 5.12, p. 178) to one another:
int ival, jval;
ival = jval = 0; // ok: each assigned 0
The first assignment is illegal because ival and pval are objects of different types. It is illegal even though zero happens to be a value that could be assigned to either object. The problem is that the result of the assignment to pval is a value of type int*, which cannot be assigned to an object of type int. On the other hand, the second assignment is fine. The string literal is converted to string, and that string is assigned to s2. The result of that assignment is s2, which is then assigned to s1.
int ival; int *pval;
ival = pval = 0; // error: cannot assign the value of a pointer to an int
string s1, s2;
s1 = s2 = "OK"; // ok: "OK" converted to string
5.4.2. Assignment Has Low Precedence
Inside a condition is another common place where assignment is used as a part of a larger expression. Writing an assignment in a condition can shorten programs and clarify the programmer's intent. For example, the following loop uses a function named get_value, which we assume returns int values. We can test those values until we obtain some desired valuesay, 42:
The program begins by getting the first value and storing it in i. Then it establishes the loop, which tests whether i is 42, and if not, does some processing. The last statement in the loop gets a value from get_value(), and the loop repeats. We can write this loop more succinctly as
int i = get_value(); // get_value returns an int
while (i != 42) {
// do something ...
i = get_value(); }
The condition now more clearly expresses our intent: We want to continue until get_value returns 42. The condition executes by assigning the result returned by get_value to i and then comparing the result of that assignment with 42.
int i;
while ((i = get_value()) != 42) {
// do something ...
}

Beware of Confusing Equality and Assignment Operators
The fact that we can use assignment in a condition can have surprising effects:
This code is legal: What happens is that 42 is assigned to i and then the result of the assignment is tested. In this case, 42 is nonzero, which is interpreted as a true value. The author of this code almost surely intended to test whether i was 42:
if (i = 42)
Bugs of this sort are notoriously difficult to find. Some, but not all, compilers are kind enough to warn about code such as this example.
if (i == 42)
Exercises Section 5.4.2
Exercise 5.11:What are the values of i and d after the each assignment:
Exercise 5.12:Explain what happens in each of the if tests:
int i; double d;
d = i = 3.5;
i = d = 3.5;
if (42 = i) // . . .
if (i = 42) // . . .
5.4.3. Compound Assignment Operators
We often apply an operator to an object and then reassign the result to that same object. As an example, consider the sum program from page 14:
This kind of operation is common not just for addition but for the other arithmetic operators and the bitwise operators. There are compound assignments for each of these operators. The general syntactic form of a compound assignment operator is
int sum = 0;
// sum values from 1 up to 10 inclusive
for (int val = 1; val <= 10; ++val)
sum += val; // equivalent to sum = sum + val
where op= may be one of the following ten operators:
a op= b;
Each compound operator is essentially equivalent to
+= -= *= /= %= // arithmetic operators
<<= >>= &= ^= |= // bitwise operators
There is one important difference: When we use the compound assignment, the left-hand operand is evaluated only once. If we write the similar longer version, that operand is evaluated twice: once as the right-hand operand and again as the left. In many, perhaps most, contexts this difference is immaterial aside from possible performance consequences.
a = a op b;
Exercises Section 5.4.3
Exercise 5.13:The following assignment is illegal. Why? How would you correct it?
Exercise 5.14:Although the following are legal, they probably do not behave as the programmer expects. Why? Rewrite the expressions as you think they should be.
double dval; int ival; int *pi;
dval = ival = pi = 0;
(a) if (ptr = retrieve_pointer() != 0)
(b) if (ival = 1024)
(c) ival += ival + 1;