Skip to main content
C△ inherits all C11 primitive types and adds several modern first-class types designed for safe, expressive systems programming. You can use every C11 type exactly as you would in standard C, and layer in C△‘s new types wherever they simplify your code. This page covers every type you can reach for in C△, with examples drawn directly from the language.

Primitive Types

The following types are inherited unchanged from C11. Their sizes, signedness, and semantics are identical to what you already know.

Pointers

C△ supports standard C-style pointers with the same * and & syntax you already know from C11. No new syntax is introduced.
C△‘s autoremove allocate feature is designed to manage heap-allocated pointer lifetimes automatically. It is not yet implemented in the current compiler — see Compiler Status.

string — First-Class String

string is a built-in, automatically memory-managed type for text. Unlike char*, you do not manage the underlying buffer yourself — the compiler handles allocation and deallocation.
Use string instead of char* for any text that doesn’t need to cross a C ABI boundary. Reserve char* for interop with external C libraries.

auto — Type Inference

Declare a variable with auto and the compiler infers its type from the initializer. The type is resolved during the simulation pass and is fully type-aware at runtime — auto does not mean “untyped”.
You can also pack multiple variables into a single auto declaration when they share the same initial value:
auto in C△ is not the C11 storage-class specifier — that meaning has been removed entirely. Writing auto with C11 intent will raise a SyntaxError.

dynam — Dynamic Array

A dynam array is a typed, resizable array that grows and shrinks at runtime. You declare it with a bracketed initializer list and modify it with built-in methods.
dynam arrays have no fixed capacity. The runtime expands or contracts the backing allocation automatically — you never call realloc manually.

tuple — Heterogeneous List

A tuple is a dynamically-sized list that holds values of mixed types. Access elements by zero-based index, append with .push(), and query length with len().
Tuples are the backbone of C△‘s variadic function support. When you declare a function with tuple args*, the compiler packs all call-site arguments into a tuple that you can iterate over at runtime.
Struct constructors/destructors (init/end), member functions, and typed struct inheritance are not yet implemented. Plain C-style structs (fields only) work via the C11 baseline. See Compiler Status.

Struct Types

C△ provides two struct variants. Choose plain struct for data types that need constructors and methods but not polymorphism. Choose typed struct when you need inheritance and want the type to be recognized natively by the compiler.
Plain structs support an init constructor lifecycle, an end destructor lifecycle, and member functions. They do not support inheritance.
The self keyword gives member functions access to the struct’s own fields. It is optional but recommended for clarity when field names shadow parameter names.
A typed struct becomes a native type in the compiler and supports single and multiple inheritance. Declare parent types with &ParentName immediately after the struct name.
Multiple inheritance chains additional parents left to right. Constructors execute in declaration order (left to right). When two parents define the same method name, qualify the call with the parent struct name to resolve the conflict:
When multiple parent types define the same method, calling that method directly on the child is ambiguous and will not compile. Always resolve conflicts by qualifying with the parent name: obj.Dog.speak().

Type Format Specifiers

Use these specifiers with printd and other formatted-output functions to match each C△ type to its correct format token. The %k specifier is unique to C△ and handles auto variables whose concrete type is only known at runtime.
When printing an auto variable whose type you don’t know at compile time, use %k. The compiler’s simulation pass resolves the underlying type and formats the value correctly.