# 5.1 — Operator precedence and associativity

Chapter introduction

This chapter builds on top of the concepts from lesson 1.8 -- Introduction to literals and operators. A quick review follows:

In mathematics, an operation is a mathematical calculation involving zero or more input values (called operands) that produces a new value (called an output value). The specific operation to be performed is denoted by a construct (typically a symbol or pair of symbols) called an operator.

For example, as children we all learn that 2 + 3 equals 5. In this case, the literals 2 and 3 are the operands, and the symbol + is the operator that tells us to apply mathematical addition on the operands to produce the new value 5.

In this chapter, we’ll discuss topics related to operators, and explore many of the common operators that C++ supports.

Operator precedence

Now, let’s consider a more complicated expression, such as 4 + 2 * 3. In order to evaluate this expression, we must understand both what the operators do, and the correct order to apply them. The order in which operators are evaluated in a compound expression is determined by an operator’s precedence. Using normal mathematical precedence rules (which state that multiplication is resolved before addition), we know that the above expression should evaluate as 4 + (2 * 3) to produce the value 10.

In C++, when the compiler encounters an expression, it must similarly analyze the expression and determine how it should be evaluated. To assist with this, all operators are assigned a level of precedence. Operators with the highest level of precedence are evaluated first.

You can see in the table below that multiplication and division (precedence level 5) have more precedence than addition and subtraction (precedence level 6). Thus, 4 + 2 * 3 evaluates as 4 + (2 * 3) because multiplication has a higher level of precedence than addition.

Operator associativity

What happens if two operators in the same expression have the same precedence level? For example, in the expression 3 * 4 / 2, the multiplication and division operators are both precedence level 5. In this case, the compiler can’t rely upon precedence alone to determine how to evaluate the result.

If two operators with the same precedence level are adjacent to each other in an expression, the operator’s associativity tells the compiler whether to evaluate the operators from left to right or from right to left. The operators in precedence level 5 have an associativity of left to right, so the expression is resolved from left to right: (3 * 4) / 2 = 6.

Table of operators

The below table is primarily meant to be a reference chart that you can refer back to in the future to resolve any precedence or associativity questions you have.

Notes:

• Precedence level 1 is the highest precedence level, and level 17 is the lowest. Operators with a higher precedence level get evaluated first.
• L->R means left to right associativity.
• R->L means right to left associativity.
Prec/Ass Operator Description Pattern
1 None ::
::
Global scope (unary)
Namespace scope (binary)
::name
class_name::member_name
2 L->R ()
()
()
{}
type()
type{}
[]
.
->
++
––
typeid
const_cast
dynamic_cast
reinterpret_cast
static_cast
sizeof…
noexcept
alignof
Parentheses
Function call
Initialization
Uniform initialization (C++11)
Functional cast
Functional cast (C++11)
Array subscript
Member access from object
Member access from object ptr
Post-increment
Post-decrement
Run-time type information
Cast away const
Run-time type-checked cast
Cast one type to another
Compile-time type-checked cast
Get parameter pack size
Compile-time exception check
Get type alignment
(expression)
function_name(parameters)
type name(expression)
type name{expression}
new_type(expression)
new_type{expression}
pointer[expression]
object.member_name
object_pointer->member_name
lvalue++
lvalue––
typeid(type) or typeid(expression)
const_cast<type>(expression)
dynamic_cast<type>(expression)
reinterpret_cast<type>(expression)
static_cast<type>(expression)
sizeof…(expression)
noexcept(expression)
alignof(Type)
3 R->L +
-
++
––
!
~
(type)
sizeof
co_await
&
*
new
new[]
delete
delete[]
Unary plus
Unary minus
Pre-increment
Pre-decrement
Logical NOT
Bitwise NOT
C-style cast
Size in bytes
Await asynchronous call
Dereference
Dynamic memory allocation
Dynamic array allocation
Dynamic memory deletion
Dynamic array deletion
+expression
-expression
++lvalue
––lvalue
!expression
~expression
(new_type)expression
sizeof(type) or sizeof(expression)
co_await expression
&lvalue
*expression
new type
new type[expression]
delete pointer
delete[] pointer
4 L->R ->*
.*
Member pointer selector
Member object selector
object_pointer->*pointer_to_member
object.*pointer_to_member
5 L->R *
/
%
Multiplication
Division
Modulus
expression * expression
expression / expression
expression % expression
6 L->R +
-
Subtraction
expression + expression
expression - expression
7 L->R <<
>>
Bitwise shift left
Bitwise shift right
expression << expression
expression >> expression
8 L->R <=> Three-way comparison expresstion <=> expression
9 L->R <
<=
>
>=
Comparison less than
Comparison less than or equals
Comparison greater than
Comparison greater than or equals
expression < expression
expression <= expression
expression > expression
expression >= expression
10 L->R ==
!=
Equality
Inequality
expression == expression
expression != expression
11 L->R & Bitwise AND expression & expression
12 L->R ^ Bitwise XOR expression ^ expression
13 L->R | Bitwise OR expression | expression
14 L->R && Logical AND expression && expression
15 L->R || Logical OR expression || expression
16 R->L throw
co_yield
?:
=
*=
/=
%=
+=
-=
<<=
>>=
&=
|=
^=
Throw expression
Yield expression
Conditional
Assignment
Multiplication assignment
Division assignment
Modulus assignment
Subtraction assignment
Bitwise shift left assignment
Bitwise shift right assignment
Bitwise AND assignment
Bitwise OR assignment
Bitwise XOR assignment
throw expression
co_yield expression
expression ? expression : expression
lvalue = expression
lvalue *= expression
lvalue /= expression
lvalue %= expression
lvalue += expression
lvalue -= expression
lvalue <<= expression
lvalue >>= expression
lvalue &= expression
lvalue |= expression
lvalue ^= expression
17 L->R , Comma operator expression, expression

You should already recognize a few of these operators, such as +, -, *, /, (), and sizeof. However, unless you have experience with another programming language, the majority of the operators in this table will probably be incomprehensible to you right now. That’s expected at this point. We’ll cover many of them in this chapter, and the rest will be introduced as there is a need for them.

Q: Where's the exponent operator?

C++ doesn’t include an operator to do exponentiation (operator^ has a different function in C++). We discuss exponentiation more in lesson 5.3 -- Modulus and Exponentiation.

Parenthesization

In normal arithmetic, you learned that you can use parenthesis to change the order of application of operations. For example, we know that 4 + 2 * 3 evaluates as 4 + (2 * 3), but if you want it to evaluate as (4 + 2) * 3 instead, you can explicitly parenthesize the expression to make it evaluate the way you want. This works in C++ because parenthesis have one of the highest precedence levels, so parenthesis generally evaluate before whatever is inside them.

Now consider an expression like x && y || z. Does this evaluate as (x && y) || z or x && (y || z)? You could look up in the table and see that && takes precedence over ||. But there are so many operators and precedence levels that it’s hard to remember them all. In order to reduce mistakes and make your code easier to understand without referencing a precedence table, it’s a good idea to parenthesize any non-trivial compound expression, so it’s clear what your intent is.

Best practice

Use parenthesis to make it clear how an expression should evaluate, even if they are technically unnecessary.

Quiz time

Question #1

You know from everyday mathematics that expressions inside of parentheses get evaluated first. For example, in the expression `(2 + 3) * 4`, the `(2 + 3)` part is evaluated first.

For this exercise, you are given a set of expressions that have no parentheses. Using the operator precedence and associativity rules in the table above, add parentheses to each expression to make it clear how the compiler will evaluate the expression.

Show Hint

 Sample problem: x = 2 + 3 % 4 Binary operator % has higher precedence than operator + or operator =, so it gets evaluated first: x = 2 + (3 % 4) Binary operator + has a higher precedence than operator =, so it gets evaluated next: Final answer: x = (2 + (3 % 4)) We now no longer need the table above to understand how this expression will evaluate.

a) x = 3 + 4 + 5;

Show Solution

b) x = y = z;

Show Solution

c) z *= ++y + 5;

Show Solution

d) a || b && c || d;

Show Solution 5.2 -- Arithmetic operators Index 4.x -- Chapter 4 summary and quiz

### 154 comments to 5.1 — Operator precedence and associativity

• Wallnuts

I know its late to ask this and I know it's not related to the topic but I must ask this, what is the difference between this inizialation

Thanks you for those who answer it

• nascardriver

Assuming you meant `int`:
The first one create an `int` an initializes to the value `32`.
The second one creates an uninitialized `int` array with 32 elements.

• Louis Cloete

Hi Alex! It seems that the note to which you refer in the table at the conditional operator has moved to another page, and thus the reference is dangling ;)

• Alex

Ha, that's quite funny. The note has been removed. Thanks!

• Shubham Gupta

Hi everyone
In the solution of part c) of quiz, it's mentioned that unary operator ++ has the highest precedence. But because the ++ here is pre-increment operator, it's precedence is same as that of + operator according to the table (both are at Level 3). Since the associativity of Level 3 is R->L, shouldn't the expression be evaluated as z *= ( ++ ( y + 5 ) )?

• Shubham Gupta

Sorry! My mistake. I mistook unary '+' operator for addition '+' operator

• learning

Not to the section 1.5 (But it should redirect you to section 1.8 which explains what binary and unary operators are: https://www.learncpp.com/cpp-tutorial/introduction-to-literals-and-operators/) Have a nice day.

• alfonso

For some reason the Rule on this page is not on green background as it shows in 0.2 - Introduction to programming languages. Actually this rule should be rather under "Best practice" section.

• Alex

This lesson hasn't been updated using the latest formatting yet. I'm workin on it! :)

• alfonso

Entries in that table are not aligned and because of that it is hard to read. The good thing is a more valuable work/learning trying to align them by myself.

• Alex

This is a known issue on small displays. I'll try to fix it when I update the lesson.

• Siti Nur Amalia

can you explain me about prefix and postfix use...

• Alex

I talk about that in two lessons. Check out lesson O.3.3.

• rani

great website, how to create it?

• Tom Barnes

I think the bitwise NOT operator (~) is missing from the precedence table.

• Alex

It's in row 3.

• hussainiMagaji

Please am I missing something? alot of comments about "pow" while I couldnt see it in the tutorial

• Alex

That topic (exponents) got moved to the next tutorial.

• Benur21

"A few operators you should already recognize: +, -, *, /, (), =, <, >, <=, and >=. These arithmetic and relational operators have the same meaning in C++ as they do in every-day usage."

No. Equality is "==", not "=".
"=" is assignment.

Also the relational operators <, >, <=, and >= were not talked about yet before this chapter. Tho these are intuitive.

• Alex

Good feedback. I've removed =, <=, and >= from the list.

• Fernando

Hi Alex, I'm using Atom with Clang(autocomplete and linter), and it suggested me to use static_cast when I tried to declare "x" as a integer, i really liked this solution instead of using that crazy function. Also I used only "pow" instead of "std::pow". I tested with both Clang and GCC with -Wall flag and both returned no warnings. Is it okay to use only "pow"??? Both GCC and Clang give me error with "cout" and "cin" without "std::" but ignore "pow".

• nascardriver

Hi Fernando!

This lesson was about operators, that's why Alex used a custom power function.

> Is it okay to use only "pow"?
Once upon a time, in C, <cmath> was <math.h>. C doesn't have namespaces, so all functions were declared in the global namespace. Along came C++, replacing <math.h> with <cmath>, and moving all functions into the @std namespace. The functions are still available in the global namespace _in some implementations_, but they don't have to. Your code might compile you some systems, but it isn't guaranteed to.
TL:DR: No

• Fernando

thx nascardriver

just another question. If i have included another library with another function "pow", the compiler would give a error or would compile with a random namespace from both libraries?

• nascardriver

You'd get an error, because functions can only be defined once (Lesson 1.8a).
Libraries shouldn't declare anything, except a namespace, in the global namespace. By doing so, name collisions can be avoided. A lot of people on learncpp are using "using namespace xyz;" which defeats this purpose, don't do it (Lesson 4.3c).

• Guardian

This is the program to convert decimal number to binary form but it only works for 1 and 2 . Does
I need to do program infinitely to convert from 1 to infinite .

#include <iostream>
#include "yoyo.h"
using namespace std;
int main()
{

cout<<"enter a number  ";
int x;
cin>>x;
double v=x/2;

int g=v*2;

cout<<"\n binary form of ";
cout<<x;
cout<<" is = ";
if(g!=x)

cout<< 0;
else
cout<<1;
int h=v/2;
int m=h*2;
if(h!=2)

cout<<0;
else
cout<<1;
return 0;
}

• nascardriver

Hi Guardian!

This is what lesson 3.7 is about, don't skip the lessons until then, you'll need them.

References
Lesson 3.7 - Converting between binary and decimal

• Himanshu Saroj

Thank you

• nascardriver

Hi Alex!

Regarding "Note that the parameters and return value of pow are of type double" and "If you want to do integer exponents, you’re best off just using your own function to do so",
this is not true, @std::pow had integer exponent overloaded functions before C++11 and has a templated overload since C++11. Also, you're saying to #include <cmath> but you're using @pow without a namespace specifier. @<cmath> doesn't guarantee definition of @pow in the global namespace.

• Alex

Thanks for the corrections! I've tweaked the wording a bit to better indicate that std::pow assumes the _base_ is a floating point number, not the exponent.

Although the templated overload in C++11 will take an int base, it converts it to a double. I've also fixed the missing std:: prefix.

• DecSco

Hey there,
first of all: Thanks for these amazing tutorials!
I would like to know, though, where that cool integer-power function is from. Is it a typical implementation for performance reasons?
And while I've gone through it in my head, finding out that it works with the examples that I thought of, I still don't know why.. Seems so unintuitive to square the base.

• Alex

See https://en.wikipedia.org/wiki/Exponentiation_by_squaring

Yes, it's a typical implementation for performance reasons. It's not really intuitive, but since it's contained in a single function we don't have to understand how it works to use it.

• Georges Theodosiou

• nascardriver

Hi Georges!

An lvalue is everything that can be at the left side of an assignment.

@x is an lvalue, @8 is an rvalue.

• Georges Theodosiou

• nascardriver

• Georges Theodosiou

Dear Mr. nascardriver, please accept my many thanks for your help on this topic so far. However I think have to come to lesson 3.3 for understand it. Regards.

• The Perplexed Programmer

Greetings!
The following program outputs '0' irrespective of the value inserted.

Could you please look into the program and suggest the necessary remedies?

Thanks.

• nascardriver

Hi!

(1 / 2) is 0, because you're calculating with integers. Use (1.0 / 2.0).
Don't use 'using namespace'.

• Rauf

return 0;

• Georges Theeodosiou

Dear Teacher, please let me suggest you add above table in "Notes:" you have to have full browser wide. Regards.

• Alex

The right sidebar is supposed to collapse at low resolutions, but it appears that has broken. I'll have to look into why.

• nascardriver

Hi Alex!

It's caused by the
<meta name="viewport" content="width=device-width">
tag in chrome, firefox works fine. Removing the tag resolved the problem but I don't know if or which side effects it introduces.

• Georges Theodosiou

Dear Teacher, please let me say my view for your table: It be much more readable if you separate levels by lines.
_______________________________________________________

Regards.

• RAR

Consider this snippet:

According to the precedence table, the expression is evaluated as z = ((y++) + 5);
Looks like value of z will be 7.

But after these two lines are executed, the values are z = 6 and y = 2. I'm confused in this part. Thank you.

• nascardriver

Hi RAR!
Your evaluation order is correct, what you missed (or wasn't covered in this lesson) is the difference of i++ and ++i.
Both will increase i by 1. i++ returns the old value of i, ++i returns the new value of i.
Here's an example

Output

So your code will evaluate as follows

• RAR

Thanks nascardriver! Understood in depth after I read chapter 3.3

• Georges Theeodosiou

output is
6
8
Regards.

• nascardriver

Hi Georges!

My code wasn't supposed to be executed in sequence, this is what I meant:

Thanks for pointing it out, I'll try to make it clearer in future posts.

• prince

you wrote in quiz solution that binary operator "="  has right to left associativity but in table you have shown it l->r i.e left to rigth associative.

• Alex

I see operator= in the table as having r->l associativity.

• Jim

NITPICKING...

When (if ever) you get the time, I think it would be easier to read the tables if each column had the same number of rows. The number would be determined (manually) by the column needing separation from the previous and next row.

For example, in Table above, the precedence 8 L->R needs only 1 row, but there are 4 operators, descriptions and patterns. Unfortunately, the descriptions need two rows, or at least the height of two rows, to see (without expanding the browser window to ~1800 pixels, with my font sizes). While I may be among the few who don't use full-width windows, centering text vertically in a box/cell is often a source of mis-matched text from one column to the next. Even more so when there are 14+ lines of operators or descriptions. I'm sure these extra rows, not spanning multiple columns will cause havoc on your CSS.

So, an item that causes ,ore than one line of text should be broken into as many rows as needed to display properly, even without enlarging the browser window. If that mean there are 28 rows for that part of the display, All the other columns should be that height also. If few rows are needed for those other columns, just hide the cell top & bottom.

This way, each item on the left will display on the same horizontal position of the item on its right. The precedence column has the fewest items, so they can still be vertically centered, as you wish.

Congratulations! You now know why tables are dead and CSS is so much better! Except when MS decides to do things differently. :deadbash:

• Alex

Fair nitpick. I'll add it to my list of things to fix. Thanks!

• Jim

Actually, I came back to delete my post, too late! Still enjoying your teaching! I think this is my third attempt at C/C++ and I think you're going to be the successful instructors! Thanks!

• Amir

Hello! In the first table on this page there's the operator *. The description should be "Refrence" it's "Dereference"

Thank you : )

• Alex

No. * is definitely a dereference (indirection). & is reference (also address-of and bitwise AND, depending on context).

• Amir

Oops! Sorry :D

• Stephane

Hi Alex, I think writing a thing like this :

has an associativity from right to left because member_name belongs to class_name ans not class_name belongs to member_name; idem for namespaces and global scopes.

• Alex

Definitely not. The other choices are defensible. Microsoft considers :: to have no associativity, because what comes before the operator and what comes after is always treated as a single unit. Other reference material treats :: as having left to right associativity, since you can't access an identifier without knowing what namespace it's in (the namespace has to be known first).

• Stephane

Thanks, I got!

• Scott

Hey there!
I just wanted to say I'm going through your tutorials and I'm loving them! I also have a question about the Quiz part d, and this might be that I really don't understand how those operators work yet... could that series of conditions be simplified to just b && c? If I'm following it right, once b && c is true, then the remaining questions are also true, right? This isn't a question about the answer, I'm just wanting to know if I am following how that works. Thanks!

• Alex

> could that series of conditions be simplified to just b && c

No.

> If I’m following it right, once b && c is true, then the remaining questions are also true, right?

Yes, but we can't assume b && c will evaluate to true.

• SotanahT

Hey there!
Seems to be an error:
On answer a), you write that the "+" sign is left to right but on the sheet mention it's right to left.
EDIT: I was confused by the + for the unary plus, my bad

Also I agree with Ole and Happilicious

Beside these minus stuff, Great work so far

• Andrew

Hi everybody. I have a question, but there is something that is driving me crazy.

How is this evaluated?

while (exp)
{
.
.
.
}
I've seen whiles with statements such as x=>10 or x<=50, but not with only a variable. How is this while triggered?

• Alex

exp is implicitly converted to a boolean value and that is evaluated. In general, a value of 0, 0.0, or nullptr will evaluate to false, and everything else will evaluate to true.

• TOVK

Great tutorials so far: simple & engaging. Currently on my first read-through. However I'd suggest compiling all the reference tables from all the different tutorial pages into a single (& overly long) reference page/glossary. One could use the CRTL + F search function to find the information that they are looking for. It'd be more convenient than searching the information from different pages & then keeping several tabs opened at the same time. It would be a good & supplementary addition to these tutorials and new programmers could keep the reference page open while debugging their code. Well, at least I would.

• Alex

Not a bad idea. I'll keep it in mind as a future enhancement. Thanks for the thought.

• danny

why doesn't the single colon have a precedence?

• Alex

Single colon isn't an operator in C++, it's just part of the syntax for doing certain things.

• Rayon

I know that a few sentences in this program are not in English ,but i don't think it matters that much because the error i keep getting is that sqrt was not declared.Do you know what the problem is?

#include <iostream>
using namespace std;

int main()
{
int a,b,c,D;
float x1,x2;
cout<<"Vnesi gi a, b i c od kvadratnata ravenka: ";
cin>>a>>b>>c;
D=b*b-4*a*c;
if(D<0) cout<<"Ravenkata nema resenie za ovie koeficienti!";
if(D==0) cout<<"Ravenkata ima edno resenie: "<<-b/2*a;
if(D>0) {
x1=(-b+sqrt(D))/(2*a);
x2=(-b-sqrt(D))/(2*a);
cout<<"Kvadratnata ravenka: "<<a<<"x^2+"<<b<<"x+"<<c<<"=0 ima dve resenija\nx1="<<x1<<"\nx2="<<x2;
}
cout<<"n\n\n";
return 0;

• Alex

You need to include the cmath header.