TYPES(2) TYPES(2)
NAME
types - c type system
SYNOPSIS
char, short, int, vlong
uchar, ushort, uint, uvlong
u8int, u16int, u32int, u64int
Rune
usize, uintptr
uintmem
schar
DESCRIPTION
The Plan 9 C compilers and system use a specialization of
the C99 type system, which has evolved over time. The com-
pilers are unsigned preserving, and char can be assumed to
be a signed value. Although the system currently makes
heavy use of ulong to represent exactly-32-bit integers and
pointers as unsigned integers, this practice is no longer
supportable with the advent of true 64-bit compilers. Hav-
ing a more explicit type set permits us to be more specific
about intent and is helpful to maintain portability to other
systems, especially Plan 9 from User Space.
The basic 8, 16, 32 and 64-bit types are char, short, int,
and vlong. Conventionally, unsigned types simply prepend a
"u" to the basic type name rather than using the unsigned
prefix.
Most programs will need no more integer types than this.
Exceptions come in two forms: the need to be specific about
use to aid in porting, and type widths fixed by hardware or
protcols. The system call interface does not fit the second
case since the compiler itself will pick the same sizes for
both kernel and user space.
To specify an integer of a particular width, the form
ubitsint is used. Types for 8, 16, 32, and 64 bit-width
specific unsigned integers are available. There are no
signed variants of these as they are not useful where size-
specific types are appropriate. As a special case, uchar is
assumed to be equivalent to u8int. Beware of using size-
specific integers in a structure as a marshalling technique.
The compiler is free to pad the structure and endian
Page 1 Plan 9 (printed 11/5/25)
TYPES(2) TYPES(2)
conversion can easily be forgotten. Consider using a struc-
ture of basic types (typically uchar) marshalled with func-
tions as in getbe(2).
The Rune type stands alone. It holds a single unicode code-
point as described in rune(2) and utf(6).
The use-specific types are usize and uintptr. Usize repre-
sents the type returned by the C sizeof operator. It is
typically the same width as a virtual address. In order to
ease the transition to 64-bits, the AMD64 compiler currently
uses a 32-bit usize. An integer representation of a
virtual-address pointer is represented by the type uintptr.
The kernel additionally needs to specify a type to represent
a physical address. Since physical addresses may be the same
size, larger (PAE) or smaller than virtual addresses,
uintmem as a physical address may be the same size, larger
(PAE), or smaller than a virtual address. Uintmem also
stores the sizes of things that uintmem might address.
Finally, schar is used when porting to other systems where
it may matter. It should not generally be used.
EXAMPLES
The C library has a number of functions which are in need of
conversion. For example,
void* malloc(usize nbytes);
int segfree(void *va, usize len);
uintptr getcallerpc(void*);
A device driver might access a 32-bit register with
u32int regval;
regval = regbase[regoff/4];
In the kernel we could convert between physical and virtual
addresses this way:
uintmem upaddr(uintptr kva);
uintptr upaddr(uintmem pa);
The actual functions use void* for kernel addresses.
SEE ALSO
8c(1), getbe(2), rune(2), utf(6),
Plan 9 from User Space, http://swtch.com/plan9port
BUGS
The spirit of the original type system has faded with time.
Page 2 Plan 9 (printed 11/5/25)