Flash tutorial · 5 / 12
5. Data Types & Pointers
Flash is a statically typed programming language. This means that variables must have a defined type, which is checked at compile-time.
1. Primitive Types
Flash contains a standard set of systems-level primitive types:
| Type | Size / Category | Description | Example |
|---|---|---|---|
u8 |
8-bit | Unsigned integer (byte) | var value u8 = 255 |
u32 |
32-bit | Unsigned integer | var value u32 = 42000 |
i32 |
32-bit | Signed integer | var value i32 = -15 |
usize |
Pointer size | Unsigned size type (size of memory address) | var len usize = 512 |
bool |
Boolean | Store either true or false |
var ok bool = true |
void |
Special | Empty or no value | Used for functions returning nothing |
noreturn |
Special | Indication that a function never returns | Used for main exit calls |
2. Pointer Types
Pointers store memory addresses and allow direct access to memory. In Flash, pointers have distinct safety and usage categories:
Single-item Pointers (*T / *mut T)
Points to exactly one value of type T in memory.
*T: Pointer to a constant (immutable) value of typeT. This is the default.*mut T: Pointer to a mutable value of typeT.
var value i32 = 42
// Create a mutable pointer to value
const ptr *mut i32 = &value
// Dereference the pointer to read/write the value
ptr.* = 100
Many-item Pointers ([*]T / [*]mut T)
Points to an array of unknown size in memory. No bounds checking is performed.
[*]T: Points to a read-only sequence of items.[*]mut T: Points to a mutable sequence of items.
Sentinel-terminated Pointers ([*:s]T)
A many-item pointer terminated by a specific sentinel value s.
- Most commonly used for C-style strings:
[*:0]u8(null-terminated string).
Alignment-Qualified Pointers (*align(N) T)
A pointer or slice type can carry an explicit alignment, written directly after the prefix and before any mut / volatile:
const page []align(16) u8 = getBuffer()
var reg *align(4) mut volatile u32 = mapRegister()
The alignment is part of the pointer type's identity — *align(4) u32 and *u32 are distinct types. Sentinel forms compose too: [*:0]align(2) mut u8.
Built-in Pointer Aliases
To make systems programming and C interoperability cleaner, Flash provides two built-in pointer aliases:
cstr— translates to[*:0]const u8(a null-terminated constant byte pointer, representing a C string).argv— translates to[*]const ?[*:0]const u8(an array of null-terminated C strings, representing command line arguments).
3. Pointer Dereferencing (p.*)
To access or modify the value at a pointer's memory address, use the .* suffix notation.
var x u32 = 10
var px *mut u32 = &x
// Access and modify via dereference
px.* = 20 // Now x is 20
[!NOTE] When accessing fields on pointers to structs, dereferencing is done automatically by the compiler. You can write
ptr.fielddirectly instead ofptr.*.field.
4. Type Aliases
A type is a compile-time value, so naming one is an ordinary const — and composite types are expressions, so no wrapper is needed:
const Byte = u8 // a primitive alias
const Bytes = []u8 // a slice alias
const MaybeLen = ?usize // an optional alias
const Handler = *fn(u8) u8 // a function-pointer alias
Aliases work at file scope and inside functions, and a composite type can sit directly in a generic argument (List([]u8)). One boundary: the infix error union E!T cannot be the value of an alias directly — name the error set and compose it at the use site instead.
5. Tuple Types & Multiple Return Values
A parenthesized list of two or more types is a tuple type, spellable wherever a type is — a return, a parameter, an alias, or nested as an element:
const Pair = (u8, bool)
// A function returning two values: the quotient and the remainder
fn divmod(a u32, b u32) (u32, u32) {
return a / b, a % b
}
A return heading a statement takes a comma-separated value list — Go's multi-return idiom. The tuple value literal stays .{ … }, and elements read by index:
t := .{ 42, true }
n := t[0]
The cleanest way to consume a multi-value return is a destructuring bind (q, r := divmod(7, 2) — see Chapter 4). A one-element (T) stays plain grouping, and a parenthesized value list like (1, 2) is rejected with a hint steering to .{ … }.
6. Function Types & Calling Conventions (callconv)
A function type — fn(P, …) R, usually behind a pointer (*fn(u8) u8) — can name an explicit calling convention between its parameter list and return type:
// An optional C-ABI function pointer: the v-table field shape
const Handler = ?*fn(u32, *mut [512]u8) callconv(.c) i32
This is the form a driver table's entries take when they cross an ABI boundary. The convention sits exactly where a function declaration puts it, and it is part of the type's identity at compile time — fn() callconv(.c) and fn() are distinct types.