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
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 1024Zahlentypen
| Typ | Beschreibung |
|---|---|
i8 i16 i32 i64 i128 | vorzeichenbehaftete Ganzzahlen |
u8 u16 u32 u64 usize | vorzeichenlose Ganzzahlen (usize = Zeigergröße, für Indizes) |
beliebig: u3, i7, u24 | Zig kennt jede Bitbreite |
f16 f32 f64 f128 | Gleitkomma |
bool, void, noreturn | Wahrheitswert, “nichts”, “kehrt nie zurück” |
comptime_int, comptime_float | Literale 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 3Hinweis
Zig führt keine impliziten Umwandlungen durch, die Information verlieren könnten. Du schreibst
@intCast,@floatFromInt,@truncateselbst. 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 2Verzweigungen 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
128Merke
const(unveränderlich) undvar; ungenutzte Variablen sind Fehler- Ganzzahltypen mit beliebiger Bitbreite (
u8,i32,u3); keine impliziten verlustbehafteten Umwandlungen - Umwandlung:
@intCast,@floatFromInt,@intFromFloat; Überlauf:+%,@addWithOverflow - Optionale Typen
?Tmitorelse,if (x) |wert|statt Null-Zeigern if,switchundwhilemit Wert;for (liste, 0..) |x, i|
Übungsaufgabe
Schreibe FizzBuzz für 1 bis 30 mit switch oder if.
Quiz zur Selbstkontrolle
Was bedeutet ?i32?
- Ein optionaler i32 (Wert oder null) (richtig)
- Eine Frage an den Benutzer
- Ein Zeiger
- Ein Fehlertyp
Wie schreibt man eine Zählschleife in Zig?
- for (0..n) |i| { … } (richtig)
- for (i = 0; i < n; i++)
- repeat n times
- loop i in n
Was bewirkt +%?
- Addition mit Überlauf-Umbruch (richtig)
- Addition mit Prozent
- Sättigende Addition
- Addition mit Fehlerprüfung
Weiter im Kurs
Zurück: Einführung und erstes Programm
Weiter: Funktionen, Arrays, Slices und Strings
Alle Kapitel: Zig im Überblick