This page contains a table of all C++ operators, along with their precedence and their associativity.

Precedence Rules and Associativity Rules

Robert Sebesta, in Programming the World Wide Web, Second Edition (Addison-Wesley, 2002, p. 127) gives an execellent summary of what the precedence rules and associativity rules of a programming language do for you. Here is his explanation, in slightly different form:

Adjacent Operators

First we need to undertand what is meant by the phrase adjacent operators. It means two operators that are separated by a single operand, such as the + and - in a + b - c or the * and ++ in *p++.

Precedence Rules

The precedence rules of a language specify which operator is evaluated first when two operators with different precedence are adjacent in an expression.

Associativity Rules

The associativity rules of a language specify which operator is evaluated first when two operators with the same precedence are adjacent in an expression.

Table of Precedence and Associativity

The table below is arranged from highest to lowest precedence as you go from top to bottom. Operators between dashed lines have the same "precedence level", of which you will note that there are 18. Associativity information is given in the center column, in which LR=Left-to-Right associativity and RL=Right-to-Left associativity).

Operators         Assoc    Description
----------------------------------------------------------------------
(expression)            parentheses used for grouping
::                  RL  (unary) global scope resolution operator
::                  LR  class scope resolution operator
----------------------------------------------------------------------
()                  LR  parentheses used for a function call
()                  LR  value construction, as in type(expression)
.                   LR  member selection via struct or class object
->                  LR  member selection via pointer
[]                  LR  array element access
const_cast          LR  specialized type cast
dynamic_cast        LR  specialized type cast
reinterpret_cast    LR  specialized type cast
static_cast         LR  specialized type cast
typeid              LR  type identification
++   --             LR  postfix versions of increment/decrement
----------------------------------------------------------------------
All the operators in this section are unary (one argument) operators.
++   --             RL  prefix  versions of increment/decrement
+ -                 RL  unary versions
!                   RL  logical NOT
~                   RL  bitwise complement ("ones complement")
&                   RL  address of
*                   RL  dereference
new                 RL  allocates memory to dynamic object
delete              RL  de-allocates memory allocated to dynamic object
new []              RL  allocates memory to dynamic array
delete []           RL  de-allocates memory allocated to dynamic array
sizeof              RL  for computing storage size of data
(type)              RL  cast (C-style type conversion)
----------------------------------------------------------------------
.*                  LR  struct/union/object pointer (member dereference)
->*                 LR  pointer to struct/union/object pointer
                        (indirect member dereference)
----------------------------------------------------------------------
*    /    %         LR  multiplication and division
----------------------------------------------------------------------
+    -              LR  addition and subtraction
----------------------------------------------------------------------
>>   <<             LR  input and output stream operators
----------------------------------------------------------------------
<    <=   >   >=    LR  inequality relational
----------------------------------------------------------------------
==   !=             LR  equality relational
----------------------------------------------------------------------
&                   LR  bitwise AND
----------------------------------------------------------------------
^                   LR  bitwise XOR
----------------------------------------------------------------------
|                   LR  bitwise OR
----------------------------------------------------------------------
&&                  LR  logical AND
----------------------------------------------------------------------
||                  LR  logical OR
----------------------------------------------------------------------
?:                  RL  conditional
----------------------------------------------------------------------
=                   RL  assignment
*=                  RL  multiplication and assignment
/=                  RL  division and assignment
%=                  RL  modulus (remainder) and assignment
+=                  RL  addition and assignment
-=                  RL  subtraction and  assignment
----------------------------------------------------------------------
throw               LR  throw exception
----------------------------------------------------------------------
,                   LR  the operator, not the separator
                        (combines two expressions into one)
----------------------------------------------------------------------

Some Comments on Operator Precedence

Precedence of operators is something that we sometimes take for granted, particularly if we are thoroughly familiar and comfortable with the standard precedence rules for the common arithmetic operators. But being too complaisant can put us at some peril, and particularly in a language like C++, which has such a variety of operators, it pays to be on our guard.

As a brief example, note from the table that the input/output operators (>> and <<) have a higher precedence than the relational operators but a lower precedence than the arithmetic operators. This means that a statement like

cout << 2 + 7;

"does the right thing" and displays a value of 9, while a statement like

cout << 2 < 7;

which you might expect to output 1 (or true), i.e., the value of the relational expression, in fact causes a syntax error, since the precedence of the operators involved means that parentheses are required as follows:

cout << (2 < 7);

The example is, of course, somewhat artificial (since how often do we really want to output the value of a conditional expression?), but it makes the point.