Data Types & Literals

Zig types are explicit: the width of an integer is part of its type, floats are IEEE-754, and literals begin as compile-time values that coerce only when safe. This lesson builds the mental model: choose the smallest correct type, and let the compiler prove conversions.

Explicit-Width Integers

Unlike most languages, Zig does not hide the hardware: you choose the exact number of bits. The compiler then rejects operations that could overflow in safe builds, which is a gift — silent overflow is a classic source of security bugs.

Integer Types

FamilyTypes
Unsignedu8 u16 u32 u64 u128 u256 usize
Signedi8 i16 i32 i64 i128 isize
Architectureusize / isize are pointer-sized; any width u1..u65535 is expressible
Compile-timecomptime_int, comptime_float — seen only in the compiler

Any bit width 1..=65535 is expressible (u7, i9, ...); common widths are just shorthands. Prefer u8/u32/u64 in practice and reserve exotic widths for packet formats and bit-level work.

Overflow Behavior

var a: u8 = 200;
const wrapped = a +% 100; // 44 — wrapping adds modulo 256, explicit
const bounded = a +| 100; // 255 — saturating stops at the maximum
const boom = a + 100;     // panic in Debug/ReleaseSafe: integer overflow

The plain + is checked; the exotic operators +% (wrapping) and +| (saturating) are deliberate escapes used only where the semantics truly need them.

Floating Point

Floats follow IEEE-754 exactly. There is no implicit integer-to-float trap: widening from integer to float is allowed implicitly, but narrowing a float into an integer always requires an explicit cast, because the result is lossy.

Float Types

  • f16 — half precision, GPU and storage
  • f32 — single precision, the default for most math
  • f64 — double precision, financial and scientific work
  • f128 — quad precision, rare and slow

Precision Pitfalls

const a: f32 = 0.1 + 0.2;
// 0.300000011920929... — IEEE-754 cannot represent 0.1 exactly
// Never compare floats with ==; use an epsilon or std.math.approxEqAbs

Booleans

A bool is exactly one value: true or false. Zig uses readable keyword operators and short-circuit evaluation (the right side runs only when needed).

Logical Operators

const ok: bool = true;
const done = ok and (10 > 5);  // true — and short-circuits
const skip = done or foo();      // true — foo() is NEVER called (short-circuit)
const neg = !done;               // false

Arrays

Arrays have a length known at compile time, written in the type: [N]T. Indexing is bounds-checked in safe builds — an out-of-range access is caught, not silent.

Array Literals

const fib = [_]u32{ 1, 1, 2, 3, 5 };
// [_] infers the length: [5]u32
const second = fib[1]; // 1 — checked at runtime in safe builds
const abc = [_]u8{ a, b, c };
// Array multiplication repeats a small array: "abcabcabc" == (_*3)

Vectors

Vectors are explicit SIMD types: @Vector(4, f32). They behave like arrays but map to CPU vector instructions when you target them with arithmetic. Use them only after profiling shows a hot loop worth vectorizing.

Compile-Time Literals

An integer literal without a declared type is a comptime_int: an exact value that does not yet exist in memory. It coerces automatically wherever a concrete integer type can hold it, which allows expressions like the array length above without declaring a type first.

Safe Coercion

const n: u32 = 40 + 2;          // comptime_int -> u32, holds fine
const big: u64 = n * n;          // promoted, also fine
const b: u8 = 300;               // COMPILE ERROR: comptime_int 300 does not fit u8
const casted: u8 = @intCast(300); // explicit, allowed only where lossless or deliberate

@intCast is the escape hatch; every use is visible in the source, and the runtime checks it in safe builds.

Common Pitfalls

Wrong Integer Width

Choosing i32 when u8 fits wastes memory and invites overflow bugs. Choose by range, then by hardware preference (u32/u64 are native on most CPUs).

Forgetting Overflow Semantics

Reading + as always-overflowing is wrong in Zig: plain operators are checked, and +%/+| are the explicit escapes. The choice is visible to anyone reviewing the code.

Next: Control Flow — if, switch, and loops as expressions.