Panoramica del linguaggio Zig

Zig 0.14 — linguaggio di sistema | nessun flusso di controllo nascosto | nessuna allocazione nascosta | nessun preprocessore | esecuzione in fase di compilazione

Paradigma

Imperativo, procedurale, orientato ai dati. Tipizzazione statica con inferenza, tipizzazione strutturale (duck) tramite comptime. Compilazione tramite LLVM + backend self-hosted. Nessun sovraccarico dell'operatore, nessuna eccezione, nessun RAII, nessuna macro.

Tipi

Categoria Tipi
Firmato int i8 i16 i32 i64 i128 isize
Intero non firmato u8 u16 u32 u64 u128 usize
Galleggiante f16 f32 f64 f128
Bool bool
Vuoto void
Mai noreturn
Matrice [N]T
Fetta []T
Puntatore *T *const T [*]T (molti articoli) [*c]T (puntatore C)
Facoltativo ?T
Errore di unione E!T
Struttura struct { field: T }
Unione union { field: T } (contrassegnato)
Enum enum { variant }
Imballato union/enum packed union packed enum
Vettore @Vector(N, T) (SIMD)
Funzione fn(params) ReturnType
Opaco opaque {}
Comptime comptime T (noto in fase di compilazione)
Qualsiasi tipo anytype (digitazione duck comptime)
Qualsiasi errore anyerror
Digitare type (tipo di prima classe)
Vuoto (zero bit) comptime void

Dichiarazioni

Costruisci Sintassi Note
Funzione fn name(params) ReturnType { body }
Variabile const x = expr; Immutabile
Mutevole var x = expr;
Costante const NAME: T = expr; Conosciuto al momento dell'acquisto
Esportazione export fn name() void { ... } Visibile al linker
Esterno extern fn name() void; Da un altro oggetto
Struttura const T = struct { field: T };
Enum const E = enum { variant };
Unione const U = union(enum) { field: T }; Taggato unione
Errore impostato const Errors = error { E1, E2 };
Prova test "name" { ... }
Blocco del tempo libero comptime { ... }
Assemblaggio in linea asm volatile ("code");
Importa const std = @import("std");

Flusso di controllo

Costruisci Sintassi Note
Se if (cond) { ... } else { ... }
Se (espressione) const x = if (cond) a else b;
Se (facoltativo) if (opt) |val| { ... } else { ... } Cattura scarta
Se (errore di unione) if (result) |val| { ... } else |err| { ... }
Mentre while (cond) { ... }
Mentre (facoltativo) while (opt) |val| { ... }
Mentre (errore) while (result) |val| { ... } else |err| { ... }
Per for (slice) |item| { ... }
Per (indice) for (slice, 0..) |item, i| { ... }
Cambia switch (expr) { variant => body, else => body } Esauriente
Pausa break;
Continua continue;
Ritorno return expr;
Differire defer expr; Esegui all'uscita dall'ambito
Errdefer errdefer expr; Esegui in caso di errore
Cattura result catch |err| { ... } Scartare o maneggiare

Cambia funzionalità

Operatori

Categoria Operatori
Aritmetica + - * / %
Avvolgimento +% -% *%
Saturazione +| -| *|
Confronto == != < > <= >=
Logico and or !
Bit per bit >> << & | ^ ~
Composto += -= *= /%= &= |= ^= <<= >>=
Nullabile orelse catch .? (scartare opzionale)
Varie .. (intervallo) ** (ptr deref multi) . (campo) .* (ptr deref)
Indirizzo di &expr

Comptime (metaprogrammazione)

fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

comptime {
    // Runs at compile time
    @compileLog("building for", @tagName(builtin.cpu));
}

// Generics via comptime parameters
fn ArrayList(comptime T: type) type {
    return struct {
        items: []T,
        fn init(self: *Self) void { ... }
    };
}

Funzionalità di tempo libero

Memoria

Operazione Sintassi Note
Assegnare allocator.alloc(T, n) Restituisce ![]T
Gratuito allocator.free(slice)
Rialloc allocator.realloc(slice, n)
Crea allocator.create(T) Elemento singolo
Distruggi allocator.destroy(ptr)
Parametro ripartitore allocator: Allocator Sempre esplicito

Allocatori

std.heap.page_allocator std.heap.arena_allocator std.heap.FixedBufferAllocator std.heap.ArenaAllocator std.heap.StackFallbackAllocator std.heap.c_allocator

La filosofia dell'allocatore di Zig

Gestione degli errori

// Error union type: ReturnType!Error
fn div(a: i32, b: i32) !i32 {
    if (b == 0) return error.DivisionByZero;
    return a / b;
}

// Try operator: early return on error
const result = try div(10, 2);

// Catch: provide default
const val = div(10, 0) catch 0;

// Global error set vs specific
fn parse() ParseError!i32 { ... }

Differire e Errdefer

{
    const buf = try allocator.alloc(u8, 100);
    defer allocator.free(buf);  // always runs at scope exit
    errdefer allocator.free(buf);  // runs only if error returned

    // ... use buf
}  // defer triggers here

Libreria standard (selezionata)

Modulo Contenuto
std.fs File, Dir, Percorso, cwd, readFile, writeFile, copyFile, deleteFile, makeDir, makePath
std.io Lettore, scrittore, bufferizzato, formattazione, stampa
std.net TcpStream, TcpListener, UdpSocket, IpAddress, DNS
std.mem copia, imposta, scambia, indexOf, dividi, unisci, allocatore, interfaccia allocatore
std.process ChildProcess, Args, Env, uscita, getSelfPath
std.time Istantaneo, nanoTime, sonno, timer, epoca
std.Thread spawn, Pool, Mutex, RwLock, Semaforo, Condizione, Atomico
std.math sqrt, sin, cos, tan, exp, log, pow, addominali, min, max, pinza
std.hash funzioni hash, crc32, sha256, sha512, md5
std.json analizzare, stringere, Valore, Array, Oggetto
std.sort ordinamento, ricerca binaria, inserimento, unione, pdqsort
std.unicode utf8, utf16, larghezza, mappatura maiuscole e minuscole
std.Build Sistema di costruzione (sostituisce make/cmake)
std.Target Rilevamento del target di compilazione incrociata
std.debug affermare, farsi prendere dal panico, stampare, scaricare, tracciare

Test

test "basic addition" {
    try std.testing.expectEqual(4, add(2, 2));
    try std.testing.expect(add(1, 1) == 2);
    try std.testing.expectError(error.DivisionByZero, div(1, 0));
}
zig test file.zig        # run tests
zig build test           # run all tests in project
zig test --name "filter" # filter test names

Compilazione incrociata

zig build-exe main.zig --target x86_64-windows  # cross-compile to Windows
zig build-exe main.zig --target aarch64-linux    # cross-compile to ARM64 Linux
zig build-exe main.zig --target riscv64-linux    # cross-compile to RISC-V

Zig viene fornito con intestazioni libc e toolchain di compilazione incrociata per tutti i principali target: non è necessario un compilatore incrociato separato.

Interoperabilità C

// Import C header
const c = @cImport({
    @cInclude("stdio.h");
});

// Link C library
pub fn main() void {
    _ = c.printf("hello %d\n", 42);
}

// Direct use of C ABI
extern "c" fn strlen(s: [*:0]u8) usize;

// Zig is a better C:
// - @cImport for headers
// - export fn for C-ABI exports
// - [*:0]T for null-terminated strings
// - @ptrCast for pointer conversion
// - packed struct for ABI-compatible layouts

Notevoli differenze rispetto a C

Compilazione

zig build-exe main.zig     # compile executable
zig build-lib lib.zig       # compile library
zig build-obj obj.zig       # compile object
zig run main.zig            # compile + run
zig test file.zig           # compile + run tests
zig fmt file.zig            # format code
zig build                   # build project (build.zig)
zig translate-c foo.h       # translate C header to Zig

Modalità di costruzione

Modalità Bandiera Controlli di sicurezza Ottimizzazioni
Debug (predefinito) Pieno Nessuno
ReleaseSafe -Doptimize=ReleaseSafe Pieno Velocità
Rilascio veloce -Doptimize=ReleaseFast Nessuno Velocità
RilasciaPiccolo -Doptimize=ReleaseSmall Nessuno Misurare