A C++ program contains a number of expressions. For example when
you write "x = ... ;" the "..." is an expression to be
evaluated and inserted into x. Similarly in "if (expr) {
...}" the expr is an expression to be evaluated to true
or false.
Expressions are built from operators like
+, -, *, /, which typically combine one or two
subexpressions. (The operators +, -, *,
/ are the usual arithmetic operators, and the star means
multiply.)
Most operators, like +, * etc., operate on two
subexpressions, on the left and right. The C++ compiler has to define
the operator precidence, i.e. say
which order an expression is evaluated in, such as whether
addition or multiplication comes first in "x + y * z".
It also as to define the operator associativity and say for exxample
whether "x - y - z" means "(x - y) - z" (we say that
- is "left associative") or "x - (y - z)" (this is what
would have happened if - were "right associative", but it isn't).
Fortunately we will see that C++ gets it right almost all of the time: * has
higher precidence than + and - really is left associative.
There are examples of expressions throughout these web pages, and many expressions
should come very naturally and easily. Some will need care.
In fact in "x = ... ;" the = is also an operator so the whole thing
before the semicolon is an expression. The operator = has
very low precidence which is why the righthand side is evaluated first.
Advice.
Operator precidence can always be overruled
by using brackets (..). If in doubt, or if it increases readability,
always use extra brackets.
Possible pitfalls.
- Using = instead of ==. Make sure you understand the
distinction between these two and use the right one.
- Using <> for "not equals". The combination <>
really does mean "not equals" in many languages, but not in C++.
C++ uses the notation != instead.
- Confusing n++ and ++n. I find that in practice I tend to use the first of these
quite a lot, and the second not so much. But if you use these at all (and
you don't have to use either) you need be clear what order things happen in.
The same goes for n-- and --n.
- Not remembering that each operator behaves slightly differently
on different types. The worst offender by far is / which is very different on int
and double. To check you understand the point, decide what the value of x after
"double x = 3.14159 + 1 / 10;" is. (Try it!)
- There is no exponentiation operator in C++ (but there are several useful library
functions that do the same job). The symbol ^ is an operator but is not exponentiation
A table of operators.
We list a number of popular operators by precidence (highest
precidence, i.e. most binding first) and state what they normally do,
and their associativity where the associativity is not to the left.
You will see that
a number of operators have the same precidence, so in these cases the order
of operators is determined by their associativity.
This list is deliberately not complete. Quite a lot
of it uses ideas we haven't covered here.
- 1st level:
-
::
- Namespace and scope resolution, e.g. std::cout.
- 2nd level:
-
.
- Member selection, e.g. v.clear() for a vector v.
-
[]
- Array element selection selection, e.g. v[5] for a vector v.
-
()
- Function call, e.g. f(5) for a function f.
-
++
- Post increment, e.g. n++ means increment n
(as n = n+1;) but return the original value of n.
-
--
- Post decrement, e.g. n-- means decrement n
(as n = n-1;) but return the original value of n.
- 3rd level:
-
++
- Pre increment, e.g. ++n means increment n
(as n = n+1;) and return the new value of n.
-
--
- Pre decrement, e.g. --n means decrement n
(as n = n-1;) and return the new value of n.
-
-
- Unary minus, e.g. -n means return the
number which is n times -1.
-
+
- Unary plus, e.g. +n means just return the
value of n.
-
!
- Not, e.g. !n means return the opposite
value for a bool: true instead of false,
and false instead of true.
- 5th level:
-
*
- Multiply, e.g. n*k means return the
value of n times k.
-
/
- Divide, e.g. n/k means return the
value of n divided by k (and rounded if this is integer division).
-
%
- Remainder or modulus, e.g. n%k means return the
remainder when n is divided by k. (Note that this
will be negative if n is negative and k
is positive.)
- 6th level:
-
+
- Addition, e.g. n+k.
-
-
- Subtraction, e.g. n-k.
- 7th level:
-
<<
- Shift left, e.g. cout << n.
-
>>
- Shift right, e.g. cin >> n.
- 8th level:
-
<
- Less than, e.g. n<k, returning a bool.
-
<=
- Less than or equal, e.g. n<=k, returning a bool.
-
>
- Greater than, e.g. n>k, returning a bool.
-
>=
- Greater than or equal, e.g. n>=k, returning a bool.
- 9th level:
-
==
- Equal, e.g. n==k, returning a bool.
-
!=
- Not equal, e.g. n!=k, returning a bool.
- 11th level:
-
^
- This operator is NOT exponentiation. I strongly recommend you forget about it and do not use it.
- 13th level:
-
&&
- Logical AND, e.g. n && k, taking two bools and returning a bool.
- 14th level:
-
||
- Logical (inclusive) OR, e.g. n || k, taking two bools and returning a bool.
- 15th level:
-
=
- Assignment, right associative, e.g. n = expr, assigning the value of expr
to n and returning this value so that multiple assignments
are possible, e.g. n = k = l = expr.
-
+=
- Assignment with +, right associative, e.g. n += expr, does n = n + expr
and returns the value of expr.
-
-=
- Assignment with -, right associative, e.g. n -= expr, does n = n - expr
and returns the value of expr.
-
*=
- Assignment with *, right associative, e.g. n *= expr, does n = n * expr
and returns the value of expr.
-
/=
- Assignment with /, right associative, e.g. n /= expr, does n = n / expr
and returns the value of expr.
-
%=
- Assignment with %, right associative, e.g. n %= expr, does n = n % expr
and returns the value of expr.
- 16th level:
-
?:
- Conditional, e.g. n ? k : m, computes n to a bool
and if true returns k else returns m. (Warning: "associativity" doesn't
really make sense for such a ternary operator. Use brackets to avoid problems.)
- 18th level:
-
,
- Sequencing, e.g. for ( i=0,j=0; i<n ; i++,j++) { ... },
computes the expressions in turn and returns the value of the last one.
C++ has many more operators (this explains the missing levels!)
but the ones above should be more than enough for normal programming
in numerics. Amongst the ones I have missed out are operators relating to pointers
and bitwise operators.