Ziglings 笔记 59: 字符与进制的变身

它是字符,也是数字

在完成了复杂的图算法测验后,Ziglings 的第 59 个练习带我们回归基础,通过 051_values.zig(注:练习编号可能因版本而异)来探讨 数值 (Values) 的本质。

在高级语言中,CharInteger 往往是泾渭分明的类型。但在 Zig 这样的系统语言中,它们之间的界限消失了。字符只是数字的另一种表现形式。

挑战:手动转码

我们需要构造字符串 “Zig”,但不能直接使用字符字面量,而是要分别使用八进制、二进制和十六进制来表示它们。

我们需要查阅 ASCII 表:

  • 'Z' = 90
  • 'i' = 105
  • 'g' = 103

解决方案

这是转换后的代码:

const print = @import("std").debug.print;

pub fn main() void {
    const zig = [_]u8{
        // 1. 'Z' (90) 转八进制
        // 90 / 8 = 11 ... 2
        // 11 / 8 = 1 ... 3
        // 1 / 8 = 0 ... 1
        // 结果: 132
        0o132, 

        // 2. 'i' (105) 转二进制
        // 105 = 64 + 32 + 8 + 1
        // 结果: 01101001
        0b01101001, 

        // 3. 'g' (103) 转十六进制
        // 103 / 16 = 6 ... 7
        // 结果: 67
        0x67, 
    };

    // 打印结果:Zig is cool.
    print("{s} is cool.\n", .{zig});
}

核心知识点总结

1. 进制前缀

Zig 的进制表示法非常标准且易记:

  • 0x: Hexadecimal (16进制)
  • 0o: Octal (8进制)
  • 0b: Binary (2进制)

2. 这里的 u8 是什么?

代码中定义的是 [_]u8。 虽然我们塞进去的是 0o132 这样看起来很奇怪的数字,但只要它的值在 0-255 之间,它就是一个合法的 u8。 当我们用 {s} 格式化打印这个数组时,Zig 会把这串数字解释为 ASCII 字符并打印出来。

3. 下划线分隔符

虽然在这个练习里没用上,但 Zig 允许 const mask = 0b1111_0000_1010_0011; 这样的写法。在定义位掩码或大数值时,这对可读性的提升是巨大的。


后续预告:我们已经了解了数值。但是,如果我有一个 u8,想把它赋值给 u16 怎么办?或者反过来?下一篇我们将探讨 Zig 中极其严格的类型转换规则 (Type Coercion)。