Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

C++  Module 2 – Types, values and expressions

C++ operators, precedence and integer division

How C++ groups an expression by precedence and associativity, why -7 / 2 is -3 and -7 % 3 is -1, and which precedence traps the compilers flag.

  • Beginner
  • 18 minutes
  • Examples run with Clang 21.0.0, GCC 16.2.0 and Python 3.14.8
  • By MySmartCoPilot
Free: 18 minutes

What you will learn

  • Evaluate expressions using precedence and associativity
  • Use / and % correctly with negative numbers
  • Add parentheses where they make intent clear

Before you start

What you’ll learn · Before you start

What you will learn

  • Evaluate expressions using precedence and associativity
  • Use / and % correctly with negative numbers
  • Add parentheses where they make intent clear

Before you start

On this page

When an expression has several operators, precedence decides which operands each one takes, and associativity decides how a run of operators of the same precedence is grouped. In C++, *, / and % bind more tightly than + and -, comparisons more tightly than &&, and && more tightly than ||, so a + b * c < d && e means ((a + (b * c)) < d) && e. Most operators group from the left, 10 - 4 - 3 is (10 - 4) - 3, while assignment groups from the right, so a = b = 0 sets both. Integer division truncates towards zero, which gives -7 / 2 == -3, and % takes the sign of its left operand, so -7 % 3 == -1. Precedence is also where many bugs hide: x & 1 == 0 does not test whether x is even. This lesson shows the rules with Apple clang 21 and GCC 16, including the warnings each compiler gives, and ends with a leap-year and weekday calculation that uses all of them.

Precedence and associativity

grouping.cpp C++ · grouping.cpp
#include <print>

int main() {
    int a = 2, b = 3, c = 4;
    std::println("a + b * c       = {:>3}   same as a + (b * c)", a + b * c);
    std::println("(a + b) * c     = {:>3}", (a + b) * c);
    std::println("20 - 6 - 4      = {:>3}   same as (20 - 6) - 4", 20 - 6 - 4);
    std::println("120 / 6 / 2     = {:>3}   same as (120 / 6) / 2", 120 / 6 / 2);
    std::println("a < b == b < c  = {}  same as (a < b) == (b < c)", a < b == b < c);
    std::println("a > b || b < c && c > 9  = {}  same as (a > b) || ((b < c) && (c > 9))", a > b || b < c && c > 9);

    int x, y;
    x = y = 7;                          // assignment groups from the right: x = (y = 7)
    x += y *= 2;                        // y becomes 14, then x becomes 7 + 14
    std::println("x = {}, y = {}", x, y);
    std::println("c > 3 ? 1 : 0 + 10  = {}   the ?: comes last: c > 3 ? 1 : (0 + 10)", c > 3 ? 1 : 0 + 10);
}
How each expression is grouped Python · grouping_session.py
from session import run

run("""
clang++ -std=c++23 -Wall -Wextra grouping.cpp -o grouping
./grouping
g++-16 -std=c++23 -Wall -Wextra grouping.cpp -o grouping
./grouping
""")

Output

$ clang++ -std=c++23 -Wall -Wextra grouping.cpp -o grouping
grouping.cpp:10:107: warning: '&&' within '||' [-Wlogical-op-parentheses]
   10 |     std::println("a > b || b < c && c > 9  = {}  same as (a > b) || ((b < c) && (c > 9))", a > b || b < c && c > 9);
      |                                                                                                  ~~ ~~~~~~^~~~~~~~
grouping.cpp:10:107: note: place parentheses around the '&&' expression to silence this warning
   10 |     std::println("a > b || b < c && c > 9  = {}  same as (a > b) || ((b < c) && (c > 9))", a > b || b < c && c > 9);
      |                                                                                                           ^       
      |                                                                                                     (             )
1 warning generated.
$ ./grouping
a + b * c       =  14   same as a + (b * c)
(a + b) * c     =  20
20 - 6 - 4      =  10   same as (20 - 6) - 4
120 / 6 / 2     =  10   same as (120 / 6) / 2
a < b == b < c  = true  same as (a < b) == (b < c)
a > b || b < c && c > 9  = false  same as (a > b) || ((b < c) && (c > 9))
x = 21, y = 14
c > 3 ? 1 : 0 + 10  = 1   the ?: comes last: c > 3 ? 1 : (0 + 10)
$ g++-16 -std=c++23 -Wall -Wextra grouping.cpp -o grouping
grouping.cpp: In function 'int main()':
grouping.cpp:9:72: warning: suggest parentheses around comparison in operand of '==' [-Wparentheses]
    9 |     std::println("a < b == b < c  = {}  same as (a < b) == (b < c)", a < b == b < c);
      |                                                                      ~~^~~
grouping.cpp:10:107: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   10 |     std::println("a > b || b < c && c > 9  = {}  same as (a > b) || ((b < c) && (c > 9))", a > b || b < c && c > 9);
      |                                                                                                     ~~~~~~^~~~~~~~
$ ./grouping
a + b * c       =  14   same as a + (b * c)
(a + b) * c     =  20
20 - 6 - 4      =  10   same as (20 - 6) - 4
120 / 6 / 2     =  10   same as (120 / 6) / 2
a < b == b < c  = true  same as (a < b) == (b < c)
a > b || b < c && c > 9  = false  same as (a > b) || ((b < c) && (c > 9))
x = 21, y = 14
c > 3 ? 1 : 0 + 10  = 1   the ?: comes last: c > 3 ? 1 : (0 + 10)

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 grouping_session.py

The $ lines are commands, and what each one printed follows it until the next $. Every line prints the value of an expression next to the same expression with all its parentheses written out. The minus and the division group from the left: grouping from the right would give 20 - (6 - 4) = 18 and 120 / (6 / 2) = 40. Assignment groups from the right, so x = y = 7 stores 7 in y and then the result in x, and x += y *= 2 doubles y before adding it to x. The conditional operator ?: sits almost at the bottom of the table, below +, so in c > 3 ? 1 : 0 + 10 the addition belongs to the third operand.

Look at the warnings too. Both compilers accept the program, yet GCC asks for parentheses around a < b == b < c, and both ask for them around the && inside an ||. The grouping there is exactly what the program prints, but it is a grouping that readers often get wrong, which is why rule ES.41 of the C++ Core Guidelines says to parenthesise when in doubt.

The C++ standard defines precedence through its grammar rather than a table, but the result can be summarised. From the operators that bind most tightly to those that bind least:

Rank Operators Grouping
1 scope a::b left
2 postfix a++ a--, call f(x), subscript a[i], member a.b p->b left
3 prefix ++a --a, unary +a -a !a ~a, *p, &a, sizeof, casts right
4 multiplicative * / % left
5 additive + - left
6 shifts << >> left
7 three-way comparison <=> left
8 relational < <= > >= left
9 equality == != left
10 bitwise AND & left
11 bitwise XOR ^ left
12 bitwise OR | left
13 logical AND && left
14 logical OR || left
15 conditional ?:, assignment = += and the other compound assignments, throw right
16 comma , left

Two rows deserve a second look. The shifts sit below +, so 1 << n + 1 shifts by n + 1; and the bitwise operators sit below the comparisons, which is the next section’s trap. When << writes to std::cout, the same row applies: std::cout << a + b prints the sum, but std::cout << a & b tries to apply & to the stream and does not compile.

Integer division and the remainder

For integers, / discards the fraction, truncating towards zero, and % gives the remainder that goes with it, so that (a / b) * b + a % b == a always holds. Since C++11 the standard fixes both, and the consequence is that the remainder has the sign of the left operand:

division.cpp C++ · division.cpp
#include <print>
#include <utility>

// Rounds the quotient down instead of towards zero (b must not be 0).
int floor_div(int a, int b) {
    int q = a / b;
    if (a % b != 0 && (a < 0) != (b < 0)) --q;
    return q;
}

// A remainder from 0 to b - 1 for a positive b, as calendars and clocks want.
int wrap_mod(int a, int b) {
    int r = a % b;
    return r < 0 ? r + b : r;
}

int main() {
    std::println("  a    b | a / b  a % b | floor_div | (a / b) * b + a % b == a");
    for (auto [a, b] : {std::pair{7, 2}, {-7, 2}, {7, -2}, {-7, -2}, {-7, 3}}) {
        std::println("{:>3}  {:>3} | {:>5}  {:>5} | {:>9} | {}", a, b, a / b, a % b, floor_div(a, b), (a / b) * b + a % b == a);
    }
    std::println("-7 % 3 = {}, but wrap_mod(-7, 3) = {}", -7 % 3, wrap_mod(-7, 3));
}
Division and remainder with every sign Python · division_session.py
from session import run

run("""
clang++ -std=c++23 -Wall -Wextra division.cpp -o division
./division
g++-16 -std=c++23 -Wall -Wextra division.cpp -o division
./division
""")

Output

$ clang++ -std=c++23 -Wall -Wextra division.cpp -o division
$ ./division
  a    b | a / b  a % b | floor_div | (a / b) * b + a % b == a
  7    2 |     3      1 |         3 | true
 -7    2 |    -3     -1 |        -4 | true
  7   -2 |    -3      1 |        -4 | true
 -7   -2 |     3     -1 |         3 | true
 -7    3 |    -2     -1 |        -3 | true
-7 % 3 = -1, but wrap_mod(-7, 3) = 2
$ g++-16 -std=c++23 -Wall -Wextra division.cpp -o division
$ ./division
  a    b | a / b  a % b | floor_div | (a / b) * b + a % b == a
  7    2 |     3      1 |         3 | true
 -7    2 |    -3     -1 |        -4 | true
  7   -2 |    -3      1 |        -4 | true
 -7   -2 |     3     -1 |         3 | true
 -7    3 |    -2     -1 |        -3 | true
-7 % 3 = -1, but wrap_mod(-7, 3) = 2

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 division_session.py

-7 / 2 is -3 rather than -4, and -7 % 2 is -1. Mathematics usually prefers the quotient rounded down and a remainder between 0 and b - 1; for positive operands the two agree, and for negative ones you write it yourself, as floor_div and wrap_mod do. wrap_mod(-7, 3) gives 2, the answer calendars and clocks need. Two more rules complete the picture: dividing by zero is undefined behaviour, and so is INT_MIN / -1, whose true result, 2,147,483,648, does not fit in an int.

&& and || stop early

&& and || evaluate their left operand first and evaluate the right one only when it can still change the result. This is called short-circuit evaluation:

short_circuit.cpp C++ · short_circuit.cpp
#include <print>
#include <vector>

bool check(const char* name, bool result) {
    std::println("  evaluating {}", name);
    return result;
}

int main() {
    std::println("false && B:");
    bool r1 = check("A", false) && check("B", true);
    std::println("true || B:");
    bool r2 = check("A", true) || check("B", true);
    std::println("false & B, with the bitwise &:");
    bool r3 = check("A", false) & check("B", true);
    std::println("results: {} {} {}", r1, r2, r3);

    // Short-circuiting makes the index check protect the element access.
    std::vector<int> v{4, 8};
    std::size_t i = 5;
    if (i < v.size() && v[i] > 0) std::println("positive");
    else std::println("index {} is outside the vector, and v[{}] was never read", i, i);
}
Which operands are evaluated Python · short_circuit_session.py
from session import run

run("""
clang++ -std=c++23 -Wall -Wextra short_circuit.cpp -o short_circuit
./short_circuit
g++-16 -std=c++23 -Wall -Wextra short_circuit.cpp -o short_circuit
./short_circuit
""")

Output

$ clang++ -std=c++23 -Wall -Wextra short_circuit.cpp -o short_circuit
short_circuit.cpp:15:15: warning: use of bitwise '&' with boolean operands [-Wbitwise-instead-of-logical]
   15 |     bool r3 = check("A", false) & check("B", true);
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                 &&
short_circuit.cpp:15:15: note: cast one or both operands to int to silence this warning
1 warning generated.
$ ./short_circuit
false && B:
  evaluating A
true || B:
  evaluating A
false & B, with the bitwise &:
  evaluating A
  evaluating B
results: false true false
index 5 is outside the vector, and v[5] was never read
$ g++-16 -std=c++23 -Wall -Wextra short_circuit.cpp -o short_circuit
$ ./short_circuit
false && B:
  evaluating A
true || B:
  evaluating A
false & B, with the bitwise &:
  evaluating A
  evaluating B
results: false true false
index 5 is outside the vector, and v[5] was never read

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 short_circuit_session.py

After false && and after true ||, the second check never runs: its output line is missing. The bitwise & has no such rule, so both checks run, and Apple clang warns that a & between two bool values was probably meant to be &&. Short-circuiting is what makes the last test safe: i < v.size() && v[i] > 0 reads v[i] only after the index has passed the check, so element 5 of a two-element vector is never touched. Swap the two operands and the program reads outside the vector before it tests anything.

Precedence traps the compilers flag

Two parse trees: x & 1 == 0 groups as x & (1 == 0) and is always false; (x & 1) == 0 tests whether x is even.written: x & 1 == 0parsed as x & (1 == 0)&x==10always falsemeant: (x & 1) == 0true for every even x==&0x1the parity test

How x & 1 == 0 is grouped

Text description of the diagram

Two expression trees side by side. In each, an operator is a circle whose branches lead to its operands.

  • Left, the expression as written, x & 1 == 0. Because == has higher precedence than &, the top node is &, with x on one branch and the comparison 1 == 0 on the other. 1 == 0 is false, which converts to 0, so the result is x & 0: always false.
  • Right, the expression as meant, (x & 1) == 0. The top node is ==, comparing x & 1 with 0. x & 1 is the lowest bit of x, so the result is true for every even x.

The comparisons bind more tightly than the bitwise operators &, ^ and |, an ordering inherited from C. So x & 1 == 0 compares 1 with 0 first, which gives false, converted to 0, and then computes x & 0, which is 0 for every x. A chain of comparisons misleads in a different way: low < mid < high is (low < mid) < high, which compares a bool, promoted to 0 or 1, with high.

Two expressions that do not mean what they say

parity.cpp

#include <print>

int main() {
    for (int x : {6, 7}) {
        bool even_wrong = x & 1 == 0;      // parsed as x & (1 == 0), which is x & 0
        bool even_right = (x & 1) == 0;
        std::println("x = {}: x & 1 == 0 gives {}, (x & 1) == 0 gives {}", x, even_wrong, even_right);
    }
}

chained.cpp

#include <print>

int main() {
    int low = 1, mid = 5, high = 3;
    bool in_order = low < mid < high;      // parsed as (low < mid) < high, which is true < 3
    std::println("low < mid < high gives {}", in_order);
    std::println("low < mid && mid < high gives {}", low < mid && mid < high);
}
What each compiler does with them Python · traps_session.py
from session import run

run("""
clang++ -std=c++23 -Wall -Wextra parity.cpp -o parity
./parity
g++-16 -std=c++23 -Wall -Wextra parity.cpp -o parity
./parity
clang++ -std=c++23 -Wall -Wextra chained.cpp -o chained
g++-16 -std=c++23 -Wall -Wextra chained.cpp -o chained
./chained
""")

Output

$ clang++ -std=c++23 -Wall -Wextra parity.cpp -o parity
parity.cpp:5:29: warning: & has lower precedence than ==; == will be evaluated first [-Wparentheses]
    5 |         bool even_wrong = x & 1 == 0;      // parsed as x & (1 == 0), which is x & 0
      |                             ^~~~~~~~
parity.cpp:5:29: note: place parentheses around the '==' expression to silence this warning
    5 |         bool even_wrong = x & 1 == 0;      // parsed as x & (1 == 0), which is x & 0
      |                             ^       
      |                               (     )
parity.cpp:5:29: note: place parentheses around the & expression to evaluate it first
    5 |         bool even_wrong = x & 1 == 0;      // parsed as x & (1 == 0), which is x & 0
      |                             ^
      |                           (    )
1 warning generated.
$ ./parity
x = 6: x & 1 == 0 gives false, (x & 1) == 0 gives true
x = 7: x & 1 == 0 gives false, (x & 1) == 0 gives false
$ g++-16 -std=c++23 -Wall -Wextra parity.cpp -o parity
parity.cpp: In function 'int main()':
parity.cpp:5:33: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses]
    5 |         bool even_wrong = x & 1 == 0;      // parsed as x & (1 == 0), which is x & 0
      |                               ~~^~~~
$ ./parity
x = 6: x & 1 == 0 gives false, (x & 1) == 0 gives true
x = 7: x & 1 == 0 gives false, (x & 1) == 0 gives false
$ clang++ -std=c++23 -Wall -Wextra chained.cpp -o chained
chained.cpp:5:31: error: chained comparison 'X < Y < Z' does not behave the same as a mathematical expression [-Wparentheses]
    5 |     bool in_order = low < mid < high;      // parsed as (low < mid) < high, which is true < 3
      |                               ^
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra chained.cpp -o chained
chained.cpp: In function 'int main()':
chained.cpp:5:25: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
    5 |     bool in_order = low < mid < high;      // parsed as (low < mid) < high, which is true < 3
      |                     ~~~~^~~~~
$ ./chained
low < mid < high gives true
low < mid && mid < high gives false

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 traps_session.py

Both compilers warn about x & 1 == 0 under -Wparentheses, which -Wall enables, and the program prints false for 6 and for 7 alike. With the parentheses, (x & 1) == 0 is true for 6. The chained comparison shows a difference between the compilers. GCC warns and builds it, and the program says that 1 < 5 < 3 is true. Apple clang refuses to build it at all: since Clang 21, a chained comparison is an error by default, as its release notes state, and -Wno-error=parentheses would turn it back into a warning. The fix in both cases is the expression you meant: (x & 1) == 0, and low < mid && mid < high.

Programmer Calculator (Bitwise) Try x & 1 on a few numbers in binary to see why the lowest bit decides odd or even.

Putting it together: leap years and weekdays

A Gregorian year is a leap year when it is divisible by 4, except century years, which are leap years only when divisible by 400. In C++ that is (year % 4 == 0 && year % 100 != 0) || year % 400 == 0. The parentheses are not needed, because && binds more tightly than ||, but they show the reader the rule’s structure, and both compilers ask for them.

The day of the week can be computed with Zeller’s congruence, a formula from a short paper by Christian Zeller. It counts January and February as months 13 and 14 of the previous year, splits the year into the century j and the year within the century k, and takes the sum of a few terms modulo 7. The formula is often printed with a - 2j term, which is the same as + 5j modulo 7 in mathematics but not in C++: when the sum is negative, % returns a negative number, and an index into a list of day names cannot be negative. This program tries both against the calendar of <chrono>, for every day of a 400-year cycle:

weekday.cpp C++ · weekday.cpp
#include <chrono>
#include <print>

bool is_leap_year(int year) {
    // && binds tighter than ||; the parentheses say so for the reader (and silence -Wparentheses).
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

// Zeller's congruence for the Gregorian calendar: 0 = Saturday, 1 = Sunday, ..., 6 = Friday.
// January and February count as months 13 and 14 of the previous year.
int zeller(int year, int month, int day) {
    if (month < 3) {
        month += 12;
        year -= 1;
    }
    int k = year % 100;
    int j = year / 100;
    return (day + 13 * (month + 1) / 5 + k + k / 4 + j / 4 + 5 * j) % 7;
}

// The same formula as it is often printed, with - 2j instead of + 5j (equal modulo 7).
int zeller_minus(int year, int month, int day) {
    if (month < 3) {
        month += 12;
        year -= 1;
    }
    int k = year % 100;
    int j = year / 100;
    return (day + 13 * (month + 1) / 5 + k + k / 4 + j / 4 - 2 * j) % 7;
}

int main() {
    constexpr const char* names[] = {"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
    using namespace std::chrono;
    int checked = 0, plus_ok = 0, minus_ok = 0, negative = 0, leap_ok = 0;
    // Every day of a 400-year cycle, checked against <chrono>.
    for (sys_days d = sys_days{2000y / January / 1}; d < sys_days{2400y / January / 1}; d += days{1}) {
        year_month_day ymd{d};
        int y = int(ymd.year()), m = int(unsigned(ymd.month())), dd = int(unsigned(ymd.day()));
        int expected = (weekday{d}.c_encoding() + 1) % 7;    // c_encoding: 0 = Sunday
        ++checked;
        plus_ok += zeller(y, m, dd) == expected;
        minus_ok += zeller_minus(y, m, dd) == expected;
        negative += zeller_minus(y, m, dd) < 0;
    }
    for (int y = 1600; y < 2400; ++y) leap_ok += is_leap_year(y) == year{y}.is_leap();
    std::println("days checked: {}", checked);
    std::println("+ 5j version correct: {}", plus_ok);
    std::println("- 2j version correct: {} (negative results: {})", minus_ok, negative);
    std::println("is_leap_year agrees with <chrono> for {} of 800 years", leap_ok);
    std::println("2000-03-01 was a {}; 2100-03-01 will be a {}", names[zeller(2000, 3, 1)], names[zeller(2100, 3, 1)]);
}
Checking 146,097 days Python · weekday_session.py
from session import run

run("""
clang++ -std=c++23 -Wall -Wextra weekday.cpp -o weekday
./weekday
g++-16 -std=c++23 -Wall -Wextra weekday.cpp -o weekday
./weekday
""")

Output

$ clang++ -std=c++23 -Wall -Wextra weekday.cpp -o weekday
$ ./weekday
days checked: 146097
+ 5j version correct: 146097
- 2j version correct: 141421 (negative results: 4676)
is_leap_year agrees with <chrono> for 800 of 800 years
2000-03-01 was a Wednesday; 2100-03-01 will be a Monday
$ g++-16 -std=c++23 -Wall -Wextra weekday.cpp -o weekday
$ ./weekday
days checked: 146097
+ 5j version correct: 146097
- 2j version correct: 141421 (negative results: 4676)
is_leap_year agrees with <chrono> for 800 of 800 years
2000-03-01 was a Wednesday; 2100-03-01 will be a Monday

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 weekday_session.py

The + 5j version agrees with <chrono> on all 146,097 days, the length of the Gregorian calendar’s 400-year cycle. The - 2j version is wrong on exactly the 4,676 days where its sum came out negative, and right on all the others, so the formula was never at fault: the remainder operator was. is_leap_year matches <chrono>’s is_leap for all 800 years it was given. In your own code, prefer <chrono>’s calendar types to hand-written formulas, and keep a formula like this one as an exercise in reading operators.

Day of the Week Calculator Check a few dates by hand against the weekday the program computes.

Interview questions

Fresher · What are -7 / 2 and -7 % 2 in C++, and why?

-7 / 2 is -3 and -7 % 2 is -1. Since C++11, integer division truncates towards zero, so the exact quotient -3.5 becomes -3, not -4. The remainder is defined so that (a / b) * b + a % b == a holds: -3 × 2 + (-1) = -7. As a result the remainder always has the sign of the left operand, which differs from the mathematical convention of a remainder from 0 to b − 1. When you need that, for example to wrap a negative value onto a clock or a ring of indexes, compute r = a % b and add b when r is negative, or keep the values non-negative from the start.

Check yourself

6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 6 What is the value of r?

    Read the code, then choose one answer.

    int r = 2 + 3 * 4 - 6 / 2;
    Show the answer to question 1

    Answer: 11

    • and / bind more tightly than + and -, so this is 2 + 12 - 3, and + and - group from the left: (2 + 12) - 3 = 11.
  2. Question 2 of 6 What do these two expressions give?

    Read the code, then choose one answer.

    -7 / 2
    -7 % 2
    Show the answer to question 2

    Answer: -3 and -1

    Integer division truncates towards zero, so -3.5 becomes -3, and the remainder makes (a / b) * b + a % b equal a: -3 × 2 + (-1) = -7. The remainder takes the sign of the left operand.

  3. Question 3 of 6 x is 6. What is the value of even?

    Read the code, then choose one answer.

    bool even = x & 1 == 0;
    Show the answer to question 3

    Answer: false

    == binds more tightly than &, so the expression is x & (1 == 0), which is x & 0, which is 0 for every x. Both compilers warn with -Wall; write (x & 1) == 0.

  4. Question 4 of 6 Why is if (i < v.size() && v[i] > 0) safe when i may be past the end of v?

    Choose one answer.

    Show the answer to question 4

    Answer: && evaluates v[i] > 0 only if i < v.size() is true

    && is evaluated from left to right and stops as soon as the result is known. With the operands swapped, v[i] would be read before the check, which is undefined behaviour for an index past the end.

  5. Question 5 of 6 What are a and b afterwards?

    Read the code, then choose one answer.

    int a, b;
    a = b = 5;
    a += b *= 2;
    Show the answer to question 5

    Answer: a is 15, b is 10

    Assignments group from the right: a = (b = 5) sets both to 5, and a += (b *= 2) doubles b to 10 and then adds that to a.

  6. Question 6 of 6 How is 1 << n + 1 grouped?

    Choose one answer.

    Show the answer to question 6

    Answer: 1 << (n + 1)

    The shift operators bind less tightly than + and -, so the addition happens first. Both compilers suggest parentheses here, because readers often expect the other grouping.

Key takeaways

  • Precedence decides grouping: * / % before + -, shifts, comparisons, the bitwise operators, &&, ||, then ?: and assignment.
  • Most operators group from the left; prefix operators, ?: and assignment group from the right.
  • Integer / truncates towards zero and % takes the sign of the left operand: -7 / 2 == -3, -7 % 3 == -1. Write a floor division or a wrapping remainder when you need one.
  • Dividing by zero and INT_MIN / -1 are undefined behaviour.
  • && and || short-circuit, so i < v.size() && v[i] > 0 is safe; & and | always evaluate both sides.
  • x & 1 == 0 means x & (1 == 0), and a < b < c means (a < b) < c. Both compilers warn; Clang 21 rejects the chained comparison. Parenthesise when in doubt.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.