Integer Overflow and Wrapping

Overflow happens when an arithmetic result exceeds the range of its type. For u8, the maximum is 255 — adding 1 to it would produce 256, which does not fit.

What Rust does by default

#![allow(unused)]
fn main() {
let x: u8 = 255;
let y = x + 1;
}
Build modeCommandBehavior
Debugcargo buildpanic at runtime
Releasecargo build --releasewraps silently to 0

This inconsistency is intentional. Debug mode surfaces bugs. Release mode prioritizes performance. The problem is that relying on either behavior makes your code unpredictable.

Explicit overflow methods

Rust provides methods that make the behavior unambiguous in both modes:

#![allow(unused)]
fn main() {
let x: u8 = 255;

x.wrapping_add(1)    // → 0     always wraps, never panics
x.saturating_add(1)  // → 255   clamps to max, never panics
x.checked_add(1)     // → None  returns Option, None on overflow
x.overflowing_add(1) // → (0, true)  result + whether it overflowed
}

Which one to use

wrapping_add / wrapping_sub — when overflow is correct and expected. Hardware emulation is the textbook use case: CHIP-8 registers are 8-bit, so arithmetic wraps exactly as the original hardware did.

#![allow(unused)]
fn main() {
self.v[x] = self.v[x].wrapping_add(nn);  // ADD Vx, byte
}

overflowing_add — when you need the result and a flag indicating overflow. Used for opcodes that write the carry or borrow to VF:

#![allow(unused)]
fn main() {
let (result, carry) = self.v[x].overflowing_add(self.v[y]);
self.v[x]   = result;
self.v[0xF] = carry as u8;  // 1 if overflow, 0 if not
}

checked_add — when overflow is an error. Not used in the CPU core, but useful in bounds checking and validation.

Why not just use +?

Using + in debug mode panics when overflow happens in a test — exactly the case that should pass. wrapping_add makes the intent explicit and consistent.


In the emulator: wrapping_add is used for 7XNN (ADD Vx, byte) which wraps silently. overflowing_add and overflowing_sub are used for 8XY4 and 8XY5 which set VF to the carry/borrow. See ADD Vx, byte and 8XY* — Arithmetic and Logic.