EMZETT.
Login

Kurz: const ist unveränderlich, var veränderlich. Der Compiler meldet ungenutzte Variablen und Variablen, die var sein könnten, aber nie verändert werden, als Fehler.

Teil des Kurses Zig

Kapitel 2 von 8 im Kurs Zig. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

const und var

const ist unveränderlich, var veränderlich. Der Compiler meldet ungenutzte Variablen und Variablen, die var sein könnten, aber nie verändert werden, als Fehler.

const std = @import("std");
 
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const name = "Mia";                  // Typ wird erschlossen
    var punkte: i32 = 10;                // Typ ausdrücklich
    punkte += 5;
    const alter: u8 = 17;
    var undefiniert: i32 = undefined;    // bewusst unbelegt
    undefiniert = 7;
    try out.print("{s} {d} {d} {d}\n", .{ name, punkte, alter, undefiniert });
 
    const a = 7;
    const b = 2;
    try out.print("{d} {d} {d} {d}\n", .{ a + b, a - b, a * b, @divTrunc(a, b) });
    try out.print("{d} {d} {d}\n", .{ a % b, @mod(-7, 3), @rem(-7, 3) });
    try out.print("{d:.3} {d}\n", .{ @as(f64, a) / b, std.math.pow(i32, 2, 10) });
}

Ausgabe:

Mia 15 17 7
9 5 14 3
1 2 -1
3.500 1024

Zahlentypen

TypBeschreibung
i8 i16 i32 i64 i128vorzeichenbehaftete Ganzzahlen
u8 u16 u32 u64 usizevorzeichenlose Ganzzahlen (usize = Zeigergröße, für Indizes)
beliebig: u3, i7, u24Zig kennt jede Bitbreite
f16 f32 f64 f128Gleitkomma
bool, void, noreturnWahrheitswert, “nichts”, “kehrt nie zurück”
comptime_int, comptime_floatLiterale zur Übersetzungszeit mit beliebiger Größe
const std = @import("std");
 
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const klein: u8 = 255;
    const mittel: i32 = -300;
    const gross: u64 = 1 << 40;
    try out.print("{d} {d} {d}\n", .{ klein, mittel, gross });
    try out.print("{d} {d} {d}\n", .{ std.math.maxInt(i32), std.math.minInt(i8), std.math.maxInt(u16) });
 
    // Umwandlungen sind explizit
    const x: i32 = 1000;
    const als_u8: u8 = @intCast(@mod(x, 256));
    const als_f: f64 = @floatFromInt(x);
    const zurueck: i32 = @intFromFloat(3.99);
    try out.print("{d} {d:.1} {d}\n", .{ als_u8, als_f, zurueck });
    try out.print("{d} {d}\n", .{ @as(u16, 40000) +% 40000, @as(i8, 127) +% 1 });   // +% : Überlauf umbrechen
 
    // Überlaufprüfung
    const ergebnis = @addWithOverflow(@as(u8, 250), 10);
    try out.print("{d} Überlauf={d}\n", .{ ergebnis[0], ergebnis[1] });
 
    // Bit-Operationen
    try out.print("{b} {b} {b} {b} {d} {d}\n", .{ 0b1100 & 0b1010, 0b1100 | 0b1010, 0b1100 ^ 0b1010, ~@as(u4, 0b1100), 1 << 5, 256 >> 2 });
    try out.print("{d} {d}\n", .{ @clz(@as(u8, 1)), @popCount(@as(u8, 0b10110)) });
}

Ausgabe:

255 -300 1099511627776
2147483647 -128 65535
232 1000.0 3
14464 -128
4 Überlauf=1
1000 1110 110 11 32 64
7 3

Hinweis

Zig führt keine impliziten Umwandlungen durch, die Information verlieren könnten. Du schreibst @intCast, @floatFromInt, @truncate selbst. Im Debug-Modus bricht ein Überlauf das Programm ab (Panic); +%, -%, *% rechnen mit Umbruch, +| mit Sättigung.

Optionale Werte

Statt null-Zeigern gibt es optionale Typen ?T:

const std = @import("std");
 
fn finde(liste: []const i32, ziel: i32) ?usize {
    for (liste, 0..) |wert, i| {
        if (wert == ziel) return i;
    }
    return null;
}
 
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const zahlen = [_]i32{ 5, 8, 13, 21 };
    const treffer = finde(&zahlen, 13);
    const keiner = finde(&zahlen, 99);
    try out.print("{any} {any}\n", .{ treffer, keiner });
 
    if (treffer) |idx| {
        try out.print("gefunden an Index {d}\n", .{idx});
    } else {
        try out.print("nicht gefunden\n", .{});
    }
    try out.print("{d} {d}\n", .{ keiner orelse 0, treffer.? });       // orelse: Standardwert, .?: auspacken
}

Ausgabe:

2 null
gefunden an Index 2
0 2

Verzweigungen und Schleifen

const std = @import("std");
 
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const punkte: u8 = 78;
 
    if (punkte >= 90) {
        try out.print("sehr gut\n", .{});
    } else if (punkte >= 75) {
        try out.print("gut\n", .{});
    } else {
        try out.print("weiter üben\n", .{});
    }
    const status = if (punkte >= 50) "bestanden" else "durchgefallen";    // if als Ausdruck
    try out.print("{s}\n", .{status});
 
    const tag: u8 = 3;
    const name = switch (tag) {
        1 => "Montag",
        2, 3, 4 => "Mitte der Woche",
        5...7 => "Ende der Woche",
        else => "unbekannt",
    };
    try out.print("{s}\n", .{name});
 
    var i: u32 = 0;
    while (i < 3) : (i += 1) {                  // Fortsetzungsausdruck nach dem Doppelpunkt
        try out.print("i={d} ", .{i});
    }
    try out.print("\n", .{});
 
    for (0..4) |k| try out.print("{d} ", .{k});  // Bereich
    try out.print("\n", .{});
 
    const namen = [_][]const u8{ "Mia", "Tom", "Zoe" };
    for (namen, 0..) |n, idx| try out.print("{d}:{s} ", .{ idx, n });
    try out.print("\n", .{});
 
    outer: for (0..3) |a| {
        for (0..3) |b| {
            if (b == 2) continue :outer;
            if (a == 2) break :outer;
            try out.print("{d}{d} ", .{ a, b });
        }
    }
    try out.print("\n", .{});
 
    var n: u32 = 1;
    const ergebnis = while (true) {             // while mit Wert über break
        n *= 2;
        if (n > 100) break n;
    };
    try out.print("{d}\n", .{ergebnis});
}

Ausgabe:

gut
bestanden
Mitte der Woche
i=0 i=1 i=2
0 1 2 3
0:Mia 1:Tom 2:Zoe
00 01 10 11
128

Merke

  • const (unveränderlich) und var; ungenutzte Variablen sind Fehler
  • Ganzzahltypen mit beliebiger Bitbreite (u8, i32, u3); keine impliziten verlustbehafteten Umwandlungen
  • Umwandlung: @intCast, @floatFromInt, @intFromFloat; Überlauf: +%, @addWithOverflow
  • Optionale Typen ?T mit orelse, if (x) |wert| statt Null-Zeigern
  • if, switch und while mit Wert; for (liste, 0..) |x, i|

Übungsaufgabe

Schreibe FizzBuzz für 1 bis 30 mit switch oder if.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Einführung und erstes Programm

Weiter: Funktionen, Arrays, Slices und Strings

Alle Kapitel: Zig im Überblick