C++ Part I · Module 4 · Expressions and Operators
Assignment and Compound Assignment
You have used the assignment operator in every program since Chapter 2.2 without anyone pointing out that it is an operator. That matters more than it sounds, because operators produce values, and so does this one. Assignment does not merely change an object — it is an expression, it has a result, and that result can be used. Two familiar pieces of C++ follow directly from it: chained assignment works for this reason, and the classic typo where a single equals sign appears in a condition compiles for this reason too. The chapter also covers the compound forms, which look like pure shorthand and quietly do something the long form does not, in a way that connects straight back to Chapter 4.2's conversion rules. None of this is difficult. All of it is the kind of thing that stays confusing for years if nobody says it once.
Foundation13 min readC++Part IFundamentalsOperators
Part I · Module 4 · Chapter 4.6 · Assignment and Compound Assignment
1. Assignment Changes an Object
cycle_count = 19;The object named on the left gets the value from the right. You have been doing this since Chapter 2.2.
Two things about it are worth stating precisely.
The left side must name something you can assign to. 19 = cycle_count; is not a thing — there is no object called 19 to change. Chapter 3.9 §2 showed the same refusal for a const object: "cannot assign to variable with const-qualified type".
The right side is evaluated first. The value has to exist before it can be stored.
2. Assignment Is Not Initialization
Chapter 3.7 §2 made this distinction and it is worth one line here because the syntax looks identical:
int cycle_count = 19; // initialization — the object's FIRST value
cycle_count = 23; // assignment — replacing an existing valueThe first is not the assignment operator at all. It is initialization, which Chapter 3.7 owns. For an int the difference is invisible; from Module 12 onward a type can do genuinely different work in the two cases, which is why the curriculum keeps the words apart.
3. Assignment Produces a Value
Here is the part that explains the rest of the chapter.
Assignment is an expression. It produces a value, and that value is the one that was just stored.
Chapter 4.1 §3 listed cycle_count = 19 as an expression with a side effect, and this is the other half of it. Measured:
int error_count = 0;
int total = 0;
total = (error_count = 5); // assignment yields the assigned value
std::cout << "error_count = " << error_count << ", total = " << total << '\n';Expected output:
error_count = 5, total = 5The inner assignment stored 5 in error_count and produced 5, which the outer assignment then stored in total.
More precisely than "produces a value": the result refers to the object that was assigned to, rather than being a detached copy. You can see that because this compiles:
(error_count = 5) = 7; // legal: assigns 5, then assigns 7 to the same objectNobody should write that. It demonstrates the point: the result of the first assignment is still the object error_count, which is why something else can be assigned to it.
C++ has a formal classification for this property of expressions, and Chapter 4.1 §6 explained why this module does not teach it. Chapter 13.6 owns it. "The result refers to the object assigned to" is the working model and it is correct.
4. Chaining, and Why It Groups Right to Left
Because assignment produces a value, assignments can chain:
int a, b, c;
a = b = c = 7;Expected output:
a=7 b=7 c=7This works because = groups right to left. The expression means a = (b = (c = 7)):
c = 7stores 7 and produces 7.b = 7stores 7 and produces 7.a = 7stores 7.
Most operators group left to right — a - b - c means (a - b) - c. Assignment is one of the exceptions, and it has to be: left-to-right grouping would mean (a = b) = c, which would assign b to a and then immediately overwrite it with c. Chapter 4.9 covers grouping generally.
Chained assignment is fine for a few variables of the same type. It stops being readable quickly, and it hides the = in a way that makes §6's typo harder to spot.
5. Compound Assignment
Every binary arithmetic and bitwise operator has a compound form:
cycles += 5; // cycles = cycles + 5
cycles -= 3;
cycles *= 2;
cycles /= 4;
cycles %= 4;Measured, starting from cycles = 10:
+= 5 -> 15
-= 3 -> 12
*= 2 -> 24
/= 4 -> 6
%= 4 -> 2The bitwise versions — &=, |=, ^=, <<=, >>= — work the same way and Chapter 4.8 uses them.
Two reasons to prefer the compound form over writing it out:
The left side is named once. buffer[compute_index()] += 1 evaluates the index expression once. Written out as buffer[compute_index()] = buffer[compute_index()] + 1, it appears twice — and if compute_index() has a side effect, it happens twice.
It cannot drift. total_cycles = total_cyclez + 1 is a typo that may still compile if both names exist. total_cycles += 1 names the object once.
6. The Typo That Compiles
The best-known C and C++ mistake, and now you can see exactly why it is possible.
#include <iostream>
int main()
{
int error_count = 0;
if (error_count = 5) { // assignment, not comparison
std::cout << "errors found\n";
}
std::cout << "error_count = " << error_count << '\n';
return 0;
}Expected output:
errors found
error_count = 5Both lines are wrong. There were no errors, and now there are five.
The mechanism is §3. error_count = 5 is an expression producing 5. A condition needs something convertible to bool, and 5 converts to true (Chapter 3.6 §3). So the branch runs — and it would run for any non-zero value, which means a condition written this way is a constant in disguise.
The compiler does warn:
eqbug.cpp:5:21: warning: using the result of an assignment as a condition
without parentheses [-Wparentheses]
eqbug.cpp:5:21: note: place parentheses around the assignment to silence
this warningRead the note, because it tells you something useful. The warning is not "you may never assign in a condition" — assigning and testing in one step is occasionally the clearest thing to write. The warning means you have not said whether you meant it. Wrapping the assignment in its own parentheses is the agreed way to say "yes, deliberately":
if ((bytes_read = read_next_chunk()) > 0) { /* ... */ }7. Mistakes Worth Making Once
Writing = where == was meant. It compiles because assignment produces a value. Keep -Wparentheses on and parenthesise deliberate assignments in conditions.
Confusing assignment with initialization. int x = 5; initializes; x = 5; assigns. Different operations, and the difference grows from Module 12.
Expecting = to group left to right. It groups right to left, which is what makes chained assignment work at all.
Assuming += is exactly the long form. It names the left side once and converts the result back to the left operand's type — measured, std::uint8_t 250 += 10 gives 4.
Writing the left side twice. buffer[next()] = buffer[next()] + 1 calls next() twice. The compound form does not.
Chaining assignments for readability. Two or three of the same type is fine. Beyond that it hides the operator and makes the §6 typo harder to see.
Assigning inside a condition without parentheses. Even when deliberate. The parentheses are how you tell the next reader — and the compiler — that it was on purpose.
8. What You Should Be Able to Say Now
- Assignment changes an object; the left side must name something assignable, and the right side is evaluated first.
- Assignment is not initialization. Chapter 3.7 owns the difference, which becomes significant from Module 12.
- Assignment is an expression and produces a value — the one just stored.
- More precisely, the result refers to the object assigned to, which is why
(x = 5) = 7compiles. The formal classification is Chapter 13.6's. - Measured:
total = (error_count = 5)leaves both at 5. =groups right to left, which is what makesa = b = c = 7work.- Compound forms exist for every binary arithmetic and bitwise operator.
- They name the left side once, so an expression with a side effect in it is evaluated once.
- Compound assignment converts the result back to the left operand's type, which can lose data quietly —
std::uint8_t250+= 10stores 4. if (x = 5)compiles because the assignment produces 5, which converts totrue.-Wparenthesescatches it, and the note names the idiom: parenthesise the assignment when you meant it.- Constants-on-the-left defends only against one case; the warning covers all of them.
9. Exercises
Exercise 1 — predict the values. After int a = 1, b = 2, c = 3; a = b = c; what does each hold, and in what order did the assignments happen?
Exercise 2 — why does it compile? Explain, in terms of this chapter, why if (count = 0) compiles, what branch it takes, and what it does to count.
Exercise 3 — deliberate or mistake? For each, say whether the author probably meant it and how you would write it to make that clear: (a) if (error_count = 5) (b) if ((bytes = read_chunk()) > 0) (c) while (c = next_char()).
Exercise 4 — the narrowing compound. std::uint8_t count = 250; count += 10; leaves count at 4. Explain each step, naming the chapter that established the promotion and the one that established the wraparound.
Exercise 5 — count the calls. How many times is index() called in each, and why does it matter? (a) buf[index()] += 1; (b) buf[index()] = buf[index()] + 1;
Exercise 6 — grouping. Explain what a = b = c would do if = grouped left to right instead, and why that would make chained assignment useless.
Exercise 7 — judge the convention. A team requires constants on the left of every ==. Give the case for it, then two specific limitations, and say what you would propose instead.
10. Summary
- Assignment changes an object, evaluates its right side first, and needs something assignable on the left.
- It is not initialization — Chapter 3.7's distinction, which grows teeth in Module 12.
- Assignment is an expression producing the value just stored, and the result refers to the object itself. Chapter 13.6 formalises that.
=groups right to left, which is what makesa = b = c = 7work.- Compound forms name the left side once and so evaluate it once.
- They convert the result back to the left operand's type — measured,
std::uint8_t250+= 10gives 4. if (x = 5)compiles because the assignment yields 5, which converts totrue.-Wparenthesescatches it, and parenthesising the assignment is how you say you meant it.- Constants-on-the-left is a partial defence; the warning is a complete one.
One group of operators is left before the bit-level work, and it is the smallest in the language: a pair that add or subtract one. They look like pure shorthand for the compound assignment above, and they are not quite, because each comes in two forms that produce different values from the same effect. The difference is invisible when you ignore the result and significant when you use it — and on types more complicated than an int it also has a cost. Chapter 4.7 covers both forms and the reason one of them is the default.
Standards & specifications
- Governing standard
- ISO/IEC 14882 (the C++ language standard)(opens ISO/IEC (JTC 1/SC 22/WG 21) in a new tab)
Defines the C++ language and its standard library — the type system and templates, the object model and object lifetime, initialisation and overload resolution, the memory model and the containers, algorithms and utilities the library provides. Like C's standard it is a FAMILY of editions (C++98/03, C++11, C++14, C++17, C++20, C++23) and the editions are NOT interchangeable: a feature this curriculum relies on may be unavailable, differently specified or merely proposed in another edition, so each lesson names the edition its claim depends on. It does not define any foreign-function interface to a hardware description language, nor what a compiler actually emits, nor platform behaviour on real silicon — those are the implementation's and the device's contracts. Working drafts published by WG21 are freely available and are what most engineers read day to day; a draft is not the published standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the C++ Programming curriculum.
