03 Beginner The Hundred
The Remainder That Went Negative
the wrap-around that forgot to wrap
#include <iostream>
int main() {
int sample[3] = {70, 80, 90}; // ring buffer holding the last three readings
int step = -7; // seven steps back around the ring
int slot = step % 3; // wrap onto 0, 1 or 2
std::cout << "laps: " << step / 3 << '\n';
std::cout << "slot: " << slot << '\n';
std::cout << "read: " << sample[slot] << '\n';
}
Run it. Which slot does the ring land on?
Answer
laps: -2, slot: -1, and typically read: 0 (GCC 11.5 on x86-64, -O0). The wrap
landed one element before the array — and nothing complained.
Why¶
C++ integer division truncates toward zero, not downward (see entry 01), so -7 / 3
is -2 where a floor would give -3. The remainder then has to satisfy
(a / b) * b + a % b == a, which forces % to carry the sign of the dividend: -7 % 3
is -1, not the 2 Python would hand you. So sample[slot] reads one int before the
array — undefined behavior, and here a quiet 0 with no crash and nothing in a log to
raise an eyebrow, which is exactly how this survives review. Change compiler or
optimization level and the number changes with it: 167772160 at GCC -O1, -7 under
Clang 18 at -O0, 540697697 under Clang at -O2. GCC's -Wall says nothing at -O0;
at -O2 the index folds to a constant and it finally speaks up with warning: array
subscript -1 is below array bounds of 'int [3]' [-Warray-bounds] — a luxury you lose the
moment step arrives at runtime.
Before C++11 the rounding direction for negative operands was implementation-defined; C++11 pinned it to truncation.
The fix¶
Push the remainder back into range — the + 3 only matters when the first % went
negative, and the second % cancels it again when it didn't:
if (slot < 0) slot += 3; does the same job with a branch. To find the ones you missed,
let the sanitizer read your subscripts:
$ g++ -std=c++17 -fsanitize=undefined main.cpp -o demo && ./demo
main.cpp:11:41: runtime error: index -1 out of bounds for type 'int [3]'
Takeaway: % follows the sign of the dividend, not the divisor — wrap an index with
((i % n) + n) % n.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo