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) |
+
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.
+
operands, respectivelyWe can characterize operators by their required operands. Most operators require one or two operands, but C++ does have one operator that requires three.
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 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.
Precedence | Examples |
---|---|
|
|
%
, is described later in the chapter.
Example | Evaluation Order |
---|---|
var = (2 + 3) * 4 |
|
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 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))); |
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 |
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.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.