2.1. Operators and Operands

Time: 00:04:03 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides (PDF)

Operators are symbols that instruct the computer to perform a single, simple task. Operands are the data, the expressions or values, on which they act or work. Operators and their operands are integral to programming, so understanding them is a prerequisite for writing and understanding programs. Many operators are familiar and easy to understand, while others are less common or have unexpected behaviors.

Most C++ operators consist of one or two characters: =, +, *, <=, or ==. The C++ syntax doesn't allow spaces or line breaks between two-character operators. Some C++ operators consist of complete words: new and return.

2 + 5 A + B 2 * A + 5 * B 3.14 * pow(A + B, 2)
(a)(b)(c)(d)
Operator and operand examples. + and * are arithmetic operators while the symbols appearing on either side of them are operands. Constants, variables, and functions returning values may all serve as operands, and programmers may intermix them when forming expressions.
  1. Operands may be constants
  2. Operands may be variables
  3. Operands may be more complex expressions: 2 * A and 5 * B are the left and right hand + operands, respectively
  4. The value returned by a non-void function may also be an operand

Number of Operands

We can characterize operators by their required operands. Most operators require one or two operands, but C++ does have one operator that requires three.

Unary Operators
Unary operators require one operand, typically following the operator but sometimes preceding it:

-N

The combination - and N forms an expression whose value is the negative of the value stored in N (e.g., - 5 = -5 or - -5 = 5). However, the operation does not change the value stored in N.
Binary Operators
Binary operators require two operands, as illustrated by the familiar arithmetic and assignment operators:

A = counter + 5;

The addition operator, +, runs before the assignment operator, =, making counter and 5 its operands. The assignment operator, =, runs next, making A and counter + 5 its operands. The example ends with a semicolon, making it a statement (specifically, an assignment statement).
Ternary Operator
The conditional operator is C++'s only ternary operator, forming it with two symbols separating the required three operands:

op1 ? op2 : op3

op1, op2, and op3 the operator's three operands. We revisit the conditional operator later in the chapter, where we add detail about its operands.
Unary, binary, and ternary operators: the number of required operands. We can easily categorize operands by the number of operands that they require.

Order of Operator Evaluation

Operators have two characteristics that affect the order in which a program evaluates them: precedence and associativity. The traditions establishing their orders may seem arbitrary, but they follow practices that evolved over decades of programming-language development.

Precedence

Precedence is an assigned operator priority. The table at the bottom of the page lists the C++ operators in precedence order: highest precedence at the top and lowest at the bottom. However, there are only three groups of operators whose relative precedence you need to memorize at this time (collectively called arithmetic operators), and they conveniently follow the precedence rules you learned in algebra.

PrecedenceExamples
  • *, /, and %
  • + and -
  • =
  • 2 * 3 * 4 → 24
  • 2 + 4 + 6 → 12
  • var = 2 + 3 * 4
Arithmetic operators. The list is from highest to lowest precedence; operators in each group have the same precedence. If var is a defined variable, the operators in the last example are evaluated in the order:
  1. 3 * 4 → 12
  2. 2 + 12 → 14
  3. a = 14
The mod or remainder operator, %, is described later in the chapter.
ExampleEvaluation Order
var = (2 + 3) * 4
  1. (2 + 3) → 5
  2. 5 * 4 → 20
  3. a = 20
Grouping parentheses change operator evaluation order. Grouping parentheses are operators with a high precedence that alter other operators' order of evaluation. The figure demonstrates grouping parentheses by adding them to the last example of the previous figure and showing the new evaluation order.

C++ allows programmers to use grouping parentheses when they are not needed and when they have no effect: (N), -(N), or (a * b) + c. C++ doesn't have a "rule" dictating the maximum number of parentheses an expression may use. Nevertheless, each opening parenthesis must match a closing parenthesis, and the closing parenthesis must be in the correct location! Each pair of extraneous parentheses makes the expression more difficult to read and increases the likelihood of an error. Therefore, I recommend using them sparingly: use them when they are needed or clarify your intent, but don't use them as a substitute for understanding precedence.

Associativity

Associativity determines the direction (left or right) in which the program evaluates operators with the same precedence. All C++ operators are either left associative (evaluated left to right) or right associative (evaluated right to left). Sometimes associativity is also called grouping, and we say the operators group left to right or group right to left. All arithmetic operators, except assignment, are left-associative (evaluated left to right). The assignment operator is right-associative (evaluated right to left), which is generally insignificant because its precedence is lower than the other operators appearing in the same statement. For example, in the statement a = (4 + 2) * 3;, the expression on the right side of = is fully evaluated before the assignment operator runs.

Example Evaluation Order
a + b + c (a + b) + c
a + b - c (a + b) - c
a * b * c (a * b) * c
a * b / c (a * b) / c
a * b / c % d ((a * b) / c) % d
a = b = c = 0; (a = (b = (c = 0)));
Associativity Evaluation Order. The "Example" column illustrates the code a programmer writes; the operators in each example have the same precedence. The parentheses in the "Evaluation Order" column explicitly show the order in which the program evaluates the operators but are otherwise unnecessary. The assignment example illustrates a shortcut for three separate assignment operations:
c = 0;
b = c;
a = b;

C++ Operator Summary

The following figure lists most of the C++ operators. Unfortunately, there are many more operators than displayable keyboard characters. Even character combinations are insufficient, implying that some C++ symbols implement more than one operator (see the parentheses in the second grouping). The compiler can distinguish an operator by where it appears in a program, and it's crucial that you also learn how to distinguish them. As you study the examples throughout the textbook, focus on where the symbols appear in each example. We don't have time to study all of the operators appearing in the following table, and we must delay our study of many until later chapters.

Operator 1 Description 2 Example Associativity 3
:: Scope resolution class::member_field
class::member_function()
Left
:: Global scope ::var Right
() Grouping (expr) Right
() Function call function(args) Left
() Functional type casting int(expr), double(expr) Right
[] Array indexing or subscripting array[index] Left
++, -- Post increment and decrement v++, v-- Right
., -> Member selection (dot and arrow) object.field, object.mfunc()
object->field, object->mfunc()
Left
! Logical negation (not) !a, !(a && b) Right
~ Bitwise complement ~k Right
+, - Unary + and - (unary + is rarely used) -N, -(a + b) Right
& Address of &v Right
* Indirection or dereference *p Right
sizeof The memory size of a variable or data type in bytes sizeof(int), sizeof(var), sizeof var; Right
new, new[] Memory and array allocator Person* p = new Person;,
int* scores = new int[100];
Right
delete, delete[] Memory and array deallocator delete p;, delete[] scores Right
.*, ->* Member object/pointer selection   Right
*, /, % Multiplication, division, and modulo 3 * x, y / z, a % 2 Left
+, - Addition and subtraction a + b, a -b Left
<<, >> Bitwise left and right shift
overloaded stream I/O
x << 2, y >> 2
cout << x, cin >> y
Left
<, >, <=, >= Relational (i.e., logical) operators: less than, greater than, less than or equal to, and greater than or equal to x < 10, x > 10, x <= 10, x >= 10 Left
==, != Equal to or not equal to x == y, x != y Left
& Bitwise AND x & 0x00008000 Left
^ Bitwise exclusive-OR 4 x ^ 0xFFFF0000 Left
| Bitwise OR x | 0x00000004 Left
&& Logical AND x && y Left
|| Logical OR x || y Left
?: Conditional operator 5 (x < y) ? x : y Left
= Assignment x = Y + b * sqrt(c); Right
+=, -=, *=, /=, %=, <<=, >>=, &=, |=, and ^= Operation with assignment (left operand must be a variable) x += 2, x -= 2, x *= 2, x /= 2, x %= 2,
x <<= 2, x >>= 2,
a &= b, a |= b, a ^= b
Right
throw Initiate an exception throw over_flow; Left
, Chain expressions (i.e., the comma operator) i = 0, j = 0, i++, j++ Left
C++ operator summary with precedence and associativity.
  1. Highest operator precedence to lowest. Operators in the same group (separated by horizontal lines) have the same precedence.
  2. Unary operators are in blue, binary operators in yellow, and the single ternary operator is in green.
  3. Left associative operators are evaluated left to right: e.g., in a+b+c, a+b is evaluated first. Right associative operators are evaluated right to left: e.g., in a=b=c, b=c is evaluated first.
  4. C++ has no exponentiation operator, so it does not use the caret or circumflex as such.
  5. Programmers typically enclose operands more complex than single constants or variables in parentheses to avoid precedence conflicts, violating the recommendation given in the grouping parentheses figure.

Operator tables like the one above are quite common. See the following lists for similar tables. You will notice that the precedence of a few of the less common operators varies from one table to the next; this variation does not cause much trouble as programmers don't generally rely on precedence for these particular operators anyway.