# Integer overflow

### February 7, 2024

#### Integer overflow

For unsigned integer values, the operations `+`, `-`, `*`, and `<<` are computed modulo 2n, where n is the bit width of the unsigned integer’s type. Loosely speaking, these unsigned integer operations discard high bits upon overflow, and programs may rely on “wrap around”.

Let’s illustrate with an example. I’ll use `uint8`, becuase it’s easier to reason about relatively small numbers, but the same holds for any of the `uint` family of types.

``````var x = uint8(254) // Initialize x near the upper limit of uint8's capacity
fmt.Println(x)
x++ // Then add one... x = 255, the max value
fmt.Println(x)
x++ // Add one more... now the high bits, those that would overflow the 8-bit value, are discarded
fmt.Println(x) // Prints 0
fmt.Println(x) // Prints 1
``````

This program prints the following output, fully demonstrating that adding to a fixed-length unsigned integer “overflows”, starting again at 0.

``````254
255
0
1
``````

For signed integers, the operations `+`, `-`, `*`, `/`, and `<<` may legally overflow and the resulting value exists and is deterministically defined by the signed integer representation, the operation, and its operands. Overflow does not cause a run-time panic. A compiler may not optimize code under the assumption that overflow does not occur. For instance, it may not assume that x < x + 1 is always true.

This will likely be a bit more confusing to many of you. Let’s modify the above code example to use `int8` instead of `uint8`:

``````var x = int8(126)
fmt.Println(x)
x++
fmt.Println(x)
x++
fmt.Println(x)
x++
fmt.Println(x)
``````

Now it prints:

``````126
127
-128
-127
``````

What tha…

To understand how the result is “deterministicly defined”, you’ll need an understanding of two’s compliment math, which is beyond the scope of this email series to fully explain. But Wikipedia can help you out if you’re really interested!

Quotes from The Go Programming Language Specification Version of August 2, 2023