- 4.1 Introduction
- 4.2 Essentials of Counter-Controlled Iteration
- 4.3 for Iteration Statement
- 4.4 Examples Using the for Statement
- 4.5 Application: Summing Even Integers
- 4.6 Application: Compound-Interest Calculations
- 4.7 do... while Iteration Statement
- 4.8 switch Multiple-Selection Statement
- 4.9 C++17 Selection Statements with Initializers
- 4.10 break and continue Statements
- 4.11 Logical Operators
- 4.12 Confusing the Equality (==) and Assignment (=) Operators
- 4.13 Objects-Natural Case Study: Using the miniz-cpp Library to Write and Read ZIP files
- 4.14 C++20 Text Formatting with Field Widths and Precisions
- 4.15 Wrap-Up
Err
4.12 Confusing the Equality (==) and Assignment (=) Operators
There’s one logic error that C++ programmers, no matter how experienced, tend to make so frequently that we feel it requires a separate section. That error is accidentally swapping the operators == (equality) and = (assignment). What makes this so damaging is that it ordinarily does not cause compilation errors. Statements with these errors tend to compile correctly and run to completion, often generating incorrect results through runtime logic errors. Today’s compilers generally can issue warnings when = is used in contexts where == is expected (see the end of this section for details on enabling this).
Two aspects of C++ contribute to these problems. One is that any expression that produces a value can be used in the decision portion of any control statement. If the expression’s value is zero, it’s treated as false. If the value is nonzero, it’s treated as true. The second is that assignments produce a value—namely, the value of the variable on the assignment operator’s left side. For example, suppose we intend to write
if (payCode == 4) { // good cout << "You get a bonus!" << "\n"; }
but we accidentally write
if (payCode = 4) { // bad cout << "You get a bonus!" << "\n"; }
The first if statement properly awards a bonus to the person whose payCode is equal to 4. The second one—which contains the error—evaluates the assignment expression in the if condition to the constant 4. Any nonzero value is true, so this condition always evaluates as true and the person always receives a bonus regardless of the pay code! Even worse, the pay code has been modified when it was only supposed to be examined!
lvalues and rvalues
You can prevent this problem with a simple trick. First, it’s helpful to know what’s allowed to the left of an assignment operator. Variable names are said to be lvalues (for “left values”) because they can be used on an assignment operator’s left side. Literals are said to be rvalues (for “right values”)—they can be used on only an assignment operator’s right side. You also can use lvalues as rvalues on an assignment’s right side, but not vice versa.
Programmers normally write conditions such as x == 7 with the variable name (an lvalue) on the left and the literal (an rvalue) on the right. Placing the literal on the left, as in 7== x (which is syntactically correct and is sometimes called a “Yoda condition”6), enables the compiler to issue an error if you accidentally replace the == operator with =. The compiler treats this as a compilation error because you can’t change a literal’s value.
Using == in Place of =
There’s another equally unpleasant situation. Suppose you want to assign a value to a variable with a simple statement like
x = 1;
but instead write
x == 1;
Here, too, this is not a syntax error. Rather, the compiler simply evaluates the expression. If x is equal to 1, the condition is true, and the expression evaluates to a nonzero (true) value. If x is not equal to 1, the condition is false and the expression evaluates to 0. Regardless of the expression’s value, there’s no assignment operator, so the value is lost. The value of x remains unaltered, probably causing an execution-time logic error. Using operator == for assignment and using operator = for equality are logic errors. Use your text editor to search for all occurrences of = in your program and check that you have the correct assignment, relational or equality operator in each place.
Enabling Warnings
Xcode automatically issues a warning when you use = where == is expected. Some compilers require you to enable warnings before they’ll issue warning messages. For GNU g++, add the -Wall (enable all warnings) flag to your compilation command—see the g++ documentation for details on enabling subsets of the potential warnings. For Visual C++:
In your solution, right-click the project’s name and select Properties.
Expand Code Analysis and select General.
For Enable Code Analysis on Build, select Yes, then click OK.