C++
algorithm
integer wrapping
efficient coding
programming techniques

Clean, efficient algorithm for wrapping integers in C

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Integer wrapping usually means taking a value that may move outside a range and folding it back into that range. A common example is turning an index like -1 into the last slot of a circular buffer, or turning n into 0 when valid indexes are 0 through n - 1.

The clean solution depends on the range. For arbitrary modulus m, the standard formula for wrapping into [0, m) is based on remainder arithmetic. In C and C++, the important detail is that negative values need special handling because % alone does not produce a mathematical modulo in the way many programmers first expect.

Wrap Into [0, m) Safely

For positive m, the standard wrap formula is:

c
int wrap(int x, int m) {
    return ((x % m) + m) % m;
}

Why the double %? Because x % m can be negative when x is negative. Adding m moves the result back into a nonnegative range, and the final % m handles the case where the first remainder was already nonnegative.

Examples for m = 5:

  • 'wrap(0, 5) gives 0'
  • 'wrap(6, 5) gives 1'
  • 'wrap(-1, 5) gives 4'
  • 'wrap(-6, 5) gives 4'

That is the general-purpose answer for circular indexing.

Wrap Into An Arbitrary Inclusive Range

If the desired range is [min, max], first shift to zero, wrap there, then shift back:

c
1int wrap_range(int x, int min, int max) {
2    int width = max - min + 1;
3    return min + ((x - min) % width + width) % width;
4}

This is useful for values such as day-of-week numbers, menu positions, or game board coordinates where the logical range does not start at zero.

Power-Of-Two Shortcut

If the modulus is a power of two and the values are nonnegative or you are working with unsigned arithmetic, a bit mask can be faster and simpler:

c
unsigned wrap_pow2(unsigned x, unsigned size) {
    return x & (size - 1);
}

This only works when size is a power of two, such as 8, 16, or 32. It is a great fit for ring buffers and low-level performance-sensitive code, but it is not a general replacement for modulo arithmetic.

Prefer Clarity Unless Profiling Says Otherwise

The modulo-based solution is already constant time and usually fast enough. In most application code, the cleanest formula is the right one. Reach for bit tricks only when the range properties make them valid and you actually care about the difference.

The more important optimization is often avoiding bugs around negative values, not shaving a tiny amount of CPU time.

Unsigned And Signed Behavior

Unsigned integer types already have defined wraparound semantics at the hardware level, but that is not the same as wrapping into an arbitrary application range. Range wrapping should still be expressed intentionally so the code says what range you actually mean.

Common Pitfalls

  • Using x % m directly and forgetting it can be negative.
  • Forgetting to validate that m or the range width is positive.
  • Applying the bit-mask shortcut when the modulus is not a power of two.
  • Using signed overflow as if it were a wrapping guarantee.
  • Writing clever wrap code that is hard to read and easy to misuse.

Summary

  • The standard wrap formula for [0, m) is ((x % m) + m) % m.
  • For [min, max], shift into zero-based space, wrap, then shift back.
  • Bit masking is a valid shortcut only for power-of-two ranges.
  • Negative values are the main reason naive % code fails.
  • Prefer clear modulo-based code unless profiling proves you need something lower-level.

Course illustration
Course illustration

All Rights Reserved.