賦值(Assignment)與運算子(Operator)是各種程式語言中最基本的操作。
賦值
在 Zig 中只有兩種賦值關鍵字:
- const:不可變的常數(immutable constant)
- var:可變的變數(mutable variable)
型別在後。無論是 const 還是 var 都要求一定要在宣告時給值。如果初始值未知或想留空,明確地賦予 undefined,這是 Zig 的「沒有隱藏」的宗旨。
pub fn main() !void {    // var a: u8;           // 這行會導致編譯錯誤    var a: u8 = undefined;  // 這是對的
    a = 100;    std.debug.print("Value: {d}\n", .{a});}不像 Rust 會明確區分編譯期常數(const)和執行期不可變變數(let),Zig 只使用 const 表達不可變的值。至於它究竟是在執行期還是編譯期確認,Zig 會盡可能將其在編譯期處理完成(如果可能的話)。
自動型別推斷
Zig 擁有自動型別推斷,可以省略型別標記,但僅限於 const 和 comptime var,一般的 var 必須明確指定型別。
pub fn main() !void {    const a = 100;    std.debug.print("Value: {d}\n", .{a});}全域變數
在 Zig 中更精準的名稱可能是模組級變數(和常數),但我還是以 C 的習慣稱其全域變數。定義在函式以外的 const 和 var 會成為全域變數,所有在此模組內的函式都可以直接存取。
只有 const 可以加上 pub 關鍵字,使其成為公開常數,讓其它模組 @import 時可以使用,就和 pub fn 是一樣的。var 不行加上 pub,Zig 不允許公開的變數。
static 區域變數
在 C 中有時會使用 static 區域變數,讓該變數的生命週期變成整個程式,但一樣只有該函式可以存取它(因為是區域的)。Zig 沒有相似的設計,如果需要變數數值在離開函式後依舊保持,直接使用全域變數,其生命週期會延續到整個模組。
強制轉型
有時會需要明確進行強制轉型。使用內建函式 @as() 達成。
const std = @import("std");
pub fn main() !void {    const a: u8 = 5;    const b = @as(u16, a);    std.debug.print("Type a: {}\n", .{@TypeOf(a)});    std.debug.print("Type b: {}\n", .{@TypeOf(b)});}Type a: u8Type b: u16在此例中,就算不用
@as(),直接打const b: u16 = a;也是可以通過編譯並正確執行,因為有 Integer Widening。
運算子
基本
Zig 的基本運算子和多數語言一樣,這裡僅列出一些常用的。
- 數學:+、-、*、/、%
- 位元:<<、>>、&、|、^、~
- 邏輯:and、or、!
- 比較:==、!=、>、>=、<、<=
一般的運算後賦值(如 +=、*=、<<=)也都有。
但是要注意 Zig 的 ++ 是陣列串聯,不是 C 的遞增算子。
還有雖然取址(Address of)和 C 一樣是 &T,但是指標解參考(Dereference、取值)是 T.*,和 C 不太一樣。
const std = @import("std");
pub fn main() void {    const a: u8 = 100;    const b: u8 = 2;    const sum: u8 = a + b;
    std.debug.print("Sum: {}", .{sum});}Sum: 102溢位
Zig 對於運算的要求相當嚴格,如果運算會發生溢位(Overflow),則必須指定溢位發生時的處理方式是飽和還是繞回,否則引發編譯期錯誤。
- 繞回運算:數值溢位後,會從最低值繞回。例如
u8的範圍是 0~255,如果 255 + 1 的話結果就會繞回到 0,255 + 2 就會繞回到 1.- 飽和運算:數值溢位後、會保持在最大/小值。例如
u8的範圍是 0~255,如果 255 + a,只要 a>0,那結果也會一直保持在u8的最大值255。
所以 Zig 除了上面的一般運算子外,還分別有 Wrapping 和 Saturating 運算的變體。繞回運算的變體是加上 %;飽和運算的變體是加上 |。例如繞回加法是 a +% b、飽和加法是 a +| b;繞回加法賦值是 a +%= b、飽和加法賦值是 a +|= b。
const std = @import("std");
pub fn main() void {    // u8: 0~255    const a: u8 = 255;    const b: u8 = 2;
    // const nor: u8 = a + b; // Error: overflow    const wrp: u8 = a +% b;   // Wrapping addition    const sat: u8 = a +| b;   // Saturating addition
    std.debug.print("Wrapping:   {}\n", .{wrp});    std.debug.print("Saturating: {}\n", .{sat});}Wrapping:   1Saturating: 255參考
- Documentation - The Zig Programming Language: Assignment
- Documentation - The Zig Programming Language: Operators
- Assignment | zig.guide
本文以 Zig 0.13.0 為主。並同時發佈在: