# Operators and arithmetic

## Default arithmetic: checked in debug, wraps in release

```cplus
let a: i32 = 10 + 20;
let c: i32 = 10 / 3;        // 3
let d: i32 = 10 % 3;        // 1
let e: i32 = 10 - 20;       // -10
```

Default arithmetic is overflow-checked in debug builds and wraps in release. Division by zero **always** traps, in both modes.

## Wrapping operators: always wrap

When you genuinely want wrap-on-overflow, use the `%`-suffixed family. They make the intent explicit, because silent overflow is a footgun you should opt into:

```cplus
let a: u8 = 250u8 +% 10u8;  // 4
let b: i8 = 100i8 *% 3i8;   // overflows, wraps silently
let c: i32 = 0 -% 1;        // -1, the canonical "this can underflow" idiom
```

## Bitwise and shifts

```cplus
let h: i32 = 0xff & 0x0f;   // 15
let i: i32 = 0xf0 | 0x0f;   // 255
let j: i32 = 0xff ^ 0xaa;   // 85
let k: i32 = 1 << 8;        // 256
let l: i32 = 256 >> 2;      // 64
let m: u32 = ~(0 as u32);   // 0xffffffff
```

Right shift on a signed type is arithmetic (sign-preserving); on an unsigned type it is logical (zero-fill).

## Byte-swap intrinsics

```cplus
let port_be: u16 = htons(8080 as u16);
let n: u32      = bswap32(0x12345678 as u32);
```

`htons` / `htonl` convert host order to network order. `bswap16` / `bswap32` / `bswap64` are unconditional swaps.

## Comparisons

```cplus
let lt: bool = a < b;
let eq: bool = a == b;      // no coercion
let ne: bool = a != b;
```

## Casts: every width change is explicit

```cplus
let x: i64 = 5;
let y: i32 = x as i32;
let f: f64 = (x as f64);
let z: usize = 10 as usize;
```

There is no `int` to `bool`, and no silent narrowing. A pointer and an integer convert only through `usize`, never through `i32`.
