Syntaxe de base de Zig

Zig est un nouveau langage de programmation, simple et efficace dans sa conception, et directement compatible avec le langage C.

Voici une introduction à quelques éléments de syntaxe de base de Zig pour vous aider à démarrer rapidement.

L'extension de fichier des fichiers de code Zig est.zig。


Premier programme Zig

Regardons d'abord le programme "Hello, World!" de Zig.

Initialisons d'abord un projet Zig :

mkdir hello-world
cd hello-world
zig init

Ensuite, créez le fichier hello.zig dans ce projet, avec le code suivant :

Exemple (fichier hello.zig)

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, World!\n", .{});
}

Analyse du code :

1. Importer la bibliothèque standard :

const std = @import("std");

Cette ligne de code importe la bibliothèque standard de Zig, similaire à dans le langage C.#include <stdio.h>。

2. Définir la fonction main :

pub fn main() !void

pubLe mot-clé indique que cette fonction est publique,fnLe mot-clé est utilisé pour définir une fonction,mainest le point d'entrée de la fonction. Le type de retour!voidindique que la fonction ne renvoie pas de valeur, mais peut renvoyer une erreur (!Le préfixe indique un type d'union d'erreur).

3. Obtenir la sortie standard :

const stdout = std.io.getStdOut().writer();

Obtenez le writer de sortie standard via la bibliothèque standard, puis appelez ses méthodes pour écrire du contenu.

4. Affichez "Hello, World!" :

try stdout.print("Hello, World!\n", .{});

printLa méthode écrit la chaîne formatée vers la sortie standard,.{}est une liste de paramètres vide.tryLe mot-clé propage les erreurs vers l'appelant lorsqu'une erreur se produit.

Ce programme illustre quelques fonctionnalités de base du langage Zig, telles que la définition de fonctions, l'utilisation de la bibliothèque standard et la gestion des erreurs.

Si vous voulez simplement exécuter un seul fichier, vous pouvez directement utiliser :

zig run hello.zig

Si vous voulez le compiler en exécutable, utilisez :

zig build-exe hello.zig

Après compilation, exécutez-le dans le terminal :

./hello

Cela affichera :

Hello, World!

Identificateurs

En Zig, les identificateurs sont des noms utilisés pour nommer des variables, des fonctions, des types, etc.

Voici quelques règles et caractéristiques concernant les identificateurs Zig :

  1. Lettres et chiffres: Les identifiants peuvent contenir des lettres (A-Z et a-z), des chiffres (0-9) et des traits de soulignement (_).

  2. Caractère de départ: Les identifiants doivent commencer par une lettre ou un trait de soulignement, et ne peuvent pas commencer par un chiffre.

  3. Sensibilité à la casse: Zig est un langage sensible à la casse, ce qui signifieVariableetvariablesont deux identifiants différents.

  4. Mots-clés et mots réservés: Certains mots spécifiques sont réservés en Zig et ne peuvent pas être utilisés comme identifiants. Par exemplefn(fonction),struct(struct),if(instruction conditionnelle), etc.

  5. Conventions de nommage: Zig recommande officiellement les conventions suivantes :

    • camelCase: Utilisé pour les noms de variables et les noms de fonctions. Par exemplemyVariable、calculateSum。
    • PascalCase: Utilisé pour les noms de types et les espaces de noms. Par exemplePoint、ArrayList。
    • SCREAMING_SNAKE_CASE: Utilisé pour les constantes connues au moment de la compilation (constantes comptime). Par exempleMAX_SIZE。
  6. Type optionnel: Zig possède un type spécial?T, qui représente une valeur optionnelle de typeT. Ceci est très utile lorsqu'on traite des valeurs qui peuvent être null.

  7. Constantes à la compilation: En utilisant lecomptimemot-clé avant un identifiant indique que l'identifiant est une constante à la compilation.

  8. Types d'erreur: En utilisant leerrormot-clé définit des types d'erreur, par exemple :

    pub fn openFile(path: []const u8) !void {
        // ...
    }
  9. Suffixe de type: En ajoutant le_tsuffixe après les noms de type est une habitude du langage C ; en Zig, vous pouvez faire de même, mais ce n'est pas obligatoire.

Mots-clés réservés

Voici quelques mots-clés réservés en Zig :

Mots-clésDescription
alignSpécifie le nombre d'octets d'alignement pour une variable ou un type
allowzeroPermet aux pointeurs de pointer vers null
andOpération ET logique
asmBloc d'assembleur en ligne
breakSortir de la boucle ou de la portée la plus proche
callconvConvention d'appel
constDéfinit une constante
continuePasser à l'itération suivante de la boucle
deferDifférer l'exécution d'une instruction jusqu'à la sortie de la portée
elseLa branche négative d'une instruction conditionnelle
enumType énumération
errdeferInstruction d'exécution différée en cas d'erreur
errorDéfinition de type d'erreur
exportExporter des symboles pour utilisation par le langage C, etc.
fnDéfinition de fonction
forBoucle de parcours
ifInstruction conditionnelle
inlineFonction inline ou boucle inline
linksectionSpécifie la section de l'éditeur de liens
noaliasUn pointeur ne peut pas être aliasé par d'autres pointeurs
noinlineEmpêche l'inlining des fonctions
nullValeur nulle pour les types optionnels
orOpération OU logique
packedSupprime le padding de la structure, compactée bit à bit
pubNiveau d'accès public
returnRetour depuis une fonction
structDéfinition de type de structure
switchInstruction de sélection à branches multiples
testBloc de code de test
threadlocalVariable locale au thread
tryEssaie d'exécuter une expression, en propageant les erreurs vers le haut en cas d'échec
unionDéfinition de type union
usingnamespaceImporter tous les membres publics d'un espace de noms dans la portée actuelle
varDéfinir une variable mutable
voidAucun type, souvent utilisé lorsqu'une fonction n'a pas de valeur de retour
whileInstruction de boucle

Syntaxe de base

1. Variables et constantes

En Zig, les variables utilisent levarmot-clé pour définir, les constantes utilisent leconstmot-clé pour définir.

const x: i32 = 10;  // 定义一个整数常量 x,值为 10
var y: f64 = 3.14;  // 定义一个浮点数变量 y,值为 3.14

2. Fonctions

Les fonctions utilisent lefnmot-clé pour définir et spécifient un type de retour.

const std = @import("std");

fn add(a: i32, b: i32) i32 {
    return a + b;
}

pub fn main() !void {
    const result = add(3, 4);
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Result: {}\n", .{result});
}

3. Instructions conditionnelles

Utiliserifetelsepour implémenter une logique conditionnelle.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const number = 10;
    if (number > 0) {
        try stdout.print("Number is positive\n", .{});
    } else {
        try stdout.print("Number is not positive\n", .{});
    }
}

4. Boucles

Zig prend en chargewhileetforles boucles.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // while 循环,: (i += 1) 是每次迭代后执行的更新表达式
    var i: i32 = 0;
    while (i < 5) : (i += 1) {
        try stdout.print("i: {}\n", .{i});
    }

    // for 循环,遍历数组
    const array = [5]i32{ 1, 2, 3, 4, 5 };
    for (array) |item| {
        try stdout.print("item: {}\n", .{item});
    }
}

5. Structures

Zig utilisestructpour définir des structures.

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const p = Point{ .x = 10, .y = 20 };
    try stdout.print("Point: ({}, {})\n", .{ p.x, p.y });
}

6. Gestion des erreurs

Zig utilise des types d'énumération d'erreur et letry / catchmot-clé pour la gestion des erreurs.

const std = @import("std");

const FileError = error{
    FileNotFound,
};

fn readFile(path: []const u8) !void {
    // 模拟一个可能失败的操作
    if (std.mem.eql(u8, path, "invalid")) {
        return FileError.FileNotFound;
    }
    // 其他操作...
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    readFile("invalid") catch |err| {
        switch (err) {
            FileError.FileNotFound => {
                try stdout.print("Error: File not found\n", .{});
            },
            else => return err,
        }
        return;
    };

    try stdout.print("File read successfully\n", .{});
}

Analyse du code :

  • catch |err|: Intercepter l'erreur et la lier à une variableerr。
  • switch (err): Faire correspondre le type d'erreur et gérer les différents cas d'erreur séparément.
  • else => return err: Propager les erreurs inattendues directement vers le haut sans les ignorer silencieusement.
  • SireadFiles'exécute avec succès (sans déclencher catch), puis continue l'exécution de l'instruction print suivante.
Autres extensions