Swift Overflow Operators (&+, &-, &*) Explained Clearly

Swift’s overflow operators let integer arithmetic continue past a type’s normal limits instead of stopping with a runtime trap. In this article, you will learn what &+, &-, and &* do, why Swift provides them, how wraparound arithmetic works, and when these operators are useful in real code.

1. What Is Overflow Operators (&+, &-, &*)?

Overflow operators are special arithmetic operators for integer types in Swift. They behave like normal addition, subtraction, and multiplication, except they allow values to wrap around when the result goes beyond the representable range of the type.

For example, a UInt8 value can store numbers from 0 to 255. If you add 1 to 255 using normal +, Swift traps at runtime. If you use &+, the result wraps back to 0.

  • &+ performs overflow addition.
  • &- performs overflow subtraction.
  • &* performs overflow multiplication.
  • They work with Swift integer types such as Int, UInt, Int8, and UInt64.
  • They do not prevent overflow; they intentionally allow wraparound behavior.
  • They are most useful when wraparound arithmetic is the desired result.

2. Why Overflow Operators Matters

Normal arithmetic in Swift is designed to be safe. If a calculation goes beyond what a type can represent, Swift stops the program rather than silently producing a wrong value. That is usually the correct choice.

However, some algorithms need arithmetic that wraps around at the type boundary. This is common in low-level programming, bit manipulation, checksums, hashing, random number generation, counters, and code that mirrors hardware or protocol behavior.

You should use overflow operators when wraparound is intentional and expected. You should not use them as a shortcut to avoid handling number range problems in ordinary business logic.

Warning: Overflow operators are not a safer version of normal arithmetic. They are a deliberate choice to get wraparound results.

3. Basic Syntax

Using the operators

The syntax looks almost the same as normal arithmetic, but each operator starts with &. The following example shows all three operators with fixed-width integer types so the wraparound is easy to see.

Swift
let maxValue: UInt8 = 255
let wrappedAdd = maxValue &+ 1

let minValue: UInt8 = 0
let wrappedSubtract = minValue &- 1

let product: UInt8 = 200
let wrappedMultiply = product &* 2

In this code, wrappedAdd becomes 0, wrappedSubtract becomes 255, and wrappedMultiply wraps to the low 8 bits of the mathematical result.

Why wraparound happens

Swift integer types have fixed storage sizes. A UInt8 stores exactly 8 bits. Once a calculation goes beyond those 8 bits, overflow operators keep only the bits that fit. That is why the result appears to cycle through the valid range.

This behavior is sometimes called modular arithmetic. For UInt8, values wrap modulo 256.

Normal arithmetic versus overflow arithmetic

The next example shows the conceptual difference between the standard operators and overflow operators.

Swift
let value: UInt8 = 255

// value + 1 would trap at runtime
let wrapped = value &+ 1

The important idea is simple: use normal operators when overflow should be treated as a bug, and use overflow operators when wraparound is the intended outcome.

4. Step-by-Step Examples

Example 1: Wrapping at the top of an unsigned range

This example shows a UInt8 moving past its maximum value.

Swift
let highest: UInt8 = 255
let next = highest &+ 1

print(next)
Output✓ Tested · Swift 6.4
0

The printed result is 0. This is the simplest form of wraparound arithmetic.

Example 2: Wrapping below zero with unsigned integers

Unsigned types cannot represent negative numbers. With normal subtraction, going below zero would trap. With &-, the result wraps to the top of the range.

Swift
let start: UInt8 = 0
let previous = start &- 1

print(previous)
Output✓ Tested · Swift 6.4
255

The result is 255. This is useful for cyclic counters or byte-based operations.

Example 3: Overflow multiplication with a small integer type

Multiplication can overflow quickly with small fixed-width types. This example makes that visible.

Swift
let a: UInt8 = 200
let b: UInt8 = 2
let result = a &* b

print(result)
Output✓ Tested · Swift 6.4
144

The mathematical result is 400, but UInt8 can only store up to 255. The value wraps and the stored result is 144.

Example 4: Signed integer wraparound

Overflow operators also work with signed integers. Here, adding past the maximum signed value wraps to the minimum signed value.

Swift
let largest: Int8 = 127
let wrapped = largest &+ 1

print(wrapped)
Output✓ Tested · Swift 6.4
-128

The result is -128. Signed integers use two’s-complement representation, so the wraparound follows that bit pattern.

5. Practical Use Cases

  • Implementing cyclic counters that should restart automatically after reaching a maximum value.
  • Working with raw bytes in binary formats, network protocols, or file parsers.
  • Building hash functions or checksum logic where modular arithmetic is part of the algorithm.
  • Writing pseudo-random number generators that depend on fixed-width integer wraparound.
  • Mirroring low-level hardware behavior where arithmetic is naturally limited by register size.
  • Performing bit-level transformations where the wrapped result is expected and meaningful.

6. Common Mistakes

Mistake 1: Using overflow operators when normal arithmetic is actually needed

Some developers use overflow operators just to avoid runtime traps, but that often hides a logic bug.

Warning: Bad pattern: wraparound used to ignore invalid numeric growth.

Swift
let cartItemCount: UInt8 = 255
let newCount = cartItemCount &+ 1

This wraps to 0, which is clearly wrong for a shopping cart count.

Use a larger type or validate the operation instead.

Swift
let cartItemCount: Int = 255
let newCount = cartItemCount + 1

The corrected version uses a more appropriate type and standard arithmetic.

Mistake 2: Expecting overflow operators to work with floating-point values

Overflow operators are for integer arithmetic, not floating-point types like Double or Float.

Warning: Bad pattern: using overflow operators with non-integer types.

Swift
// This does not compile
let value: Double = 10.5
// let result = value &+ 1.0

Use normal floating-point arithmetic instead.

Swift
let value: Double = 10.5
let result = value + 1.0

The corrected code uses the standard operator because floating-point types follow different numeric rules.

Mistake 3: Forgetting that type size changes the result

The same arithmetic can produce different wrapped results depending on whether you use UInt8, UInt16, or UInt32.

Warning: Bad pattern: assuming all integer types wrap the same way.

Swift
let small: UInt8 = 250
let wrapped = small &+ 10

This wraps because UInt8 has a small range.

Swift
let larger: UInt16 = 250
let result = larger &+ 10

Here the result is simply 260 because UInt16 has room for that value.

7. Best Practices

Practice 1: Use overflow operators only when wraparound is part of the design

Make your intent explicit. If the algorithm depends on modular arithmetic, overflow operators communicate that clearly to readers.

Swift
var byte: UInt8 = 255
byte = byte &+ 1

This is appropriate because wrapping from 255 to 0 is intentional.

Practice 2: Prefer fixed-width integer types when exact overflow behavior matters

If you rely on exact bit width, use types like UInt8, UInt32, or Int16 instead of platform-sized types when consistency is important.

Swift
let seed: UInt32 = 4_294_967_295
let nextSeed = seed &+ 1

This always wraps the same way because UInt32 has a known width.

Practice 3: Add comments when the wraparound may not be obvious

Overflow arithmetic can surprise readers who expect normal safety checks. A short comment helps explain why it is correct here.

Swift
let checksum: UInt8 = 250
// Wraparound is intentional because the protocol uses byte-sized modular arithmetic.
let updatedChecksum = checksum &+ 10

The code is clearer because the reason for using &+ is documented.

8. Limitations and Edge Cases

  • Overflow operators apply to integer types, not floating-point numbers.
  • The wrapped result depends on the type’s bit width. A calculation on UInt8 may wrap while the same one on UInt64 may not.
  • Int and UInt are platform-sized types, so their exact range depends on the target architecture.
  • Signed wraparound can be harder to reason about than unsigned wraparound because negative values are represented using two’s complement.
  • Overflow operators do not report whether overflow happened. They only give the wrapped result.
  • If you need both the result and an overflow flag, methods such as addingReportingOverflow(_:), subtractingReportingOverflow(_:), and multipliedReportingOverflow(by:) may be a better fit.

Overflow operators are useful, but if you need to detect overflow instead of silently wrapping, the reporting APIs are often the better tool.

9. Practical Mini Project

Let’s build a tiny byte counter that simulates a one-byte device register. A one-byte register can store values from 0 to 255. Incrementing past the maximum should wrap back to 0.

Swift
struct ByteCounter {
    private(set) var value: UInt8 = 0

    mutating func increment() {
        value = value &+ 1
    }

    mutating func decrement() {
        value = value &- 1
    }
}

var counter = ByteCounter()

for _ in 1...3 {
    counter.decrement()
    print(counter.value)
}

counter = ByteCounter()
for _ in 1...257 {
    counter.increment()
}

print(counter.value)
Output✓ Tested · Swift 6.4
255
254
253
1

This small project demonstrates both directions of wraparound. Starting from 0, decrementing three times produces 255, 254, and 253. Then incrementing 257 times wraps once and ends at 1.

The example is simple, but it models real situations where storage size is fixed and cyclic arithmetic is expected.

10. Key Points

  • &+, &-, and &* are Swift’s integer overflow operators.
  • They allow arithmetic to wrap around instead of trapping at runtime.
  • They are useful when modular arithmetic is intentional, such as byte processing or low-level algorithms.
  • The wrapped result depends on the specific integer type and its bit width.
  • They should not be used to hide ordinary numeric bugs in application logic.
  • If you need to know whether overflow occurred, use the reporting overflow methods instead.

11. Practice Exercise

Build a small program that simulates a one-byte score value.

  • Create a UInt8 variable named score starting at 254.
  • Add 3 using an overflow operator.
  • Subtract 5 using an overflow operator.
  • Print the intermediate and final results.

Expected output: the value should wrap during addition and still produce a valid UInt8 result after subtraction.

Hint: Start with 254, then apply &+ 3, then &- 5.

Show solution
Swift
var score: UInt8 = 254

score = score &+ 3
print("After adding 3: \(score)")

score = score &- 5
print("After subtracting 5: \(score)")
Output✓ Tested · Swift 6.4
After adding 3: 1
After subtracting 5: 252

This solution first wraps 254 forward by three steps, giving 1. It then subtracts five with wraparound, producing 252.

12. Final Summary

Swift overflow operators give you explicit control over wraparound arithmetic for integers. Instead of trapping when a value goes beyond the range of its type, &+, &-, and &* keep the calculation within the type’s fixed bit width and return the wrapped result.

That behavior is powerful when it matches the problem you are solving, especially in byte manipulation, hashing, cyclic counters, and low-level data processing. It is not a replacement for normal arithmetic safety, though. In most app code, standard operators are still the better choice because they expose range errors instead of hiding them.

A good next step is to learn Swift’s overflow-reporting methods so you can compare intentional wraparound with arithmetic that also tells you whether an overflow occurred.