diff --git a/course/basic/define-variable.md b/course/basic/define-variable.md index a99c3e28..ac8f536b 100644 --- a/course/basic/define-variable.md +++ b/course/basic/define-variable.md @@ -30,7 +30,7 @@ outline: deep 如果一定要使用不符合这些规定的名称(例如与外部库的链接),那么请使用 `@""` 语法。 -<<<@/code/release/define_variable.zig#indentifier +<<<@/code/release/define_variable.zig#identifier ::: info 🅿️ 提示 @@ -50,11 +50,15 @@ zig 使用 `const` 作为关键字来声明常量,它无法再被更改,只 <<<@/code/release/define_variable.zig#undefined -::: warning ⚠️ 警告 +使用 `undefined` 初始化的变量不会执行任何初始化操作,我们无法预知它的初始值。 + +因此,`undefined` 常用于初始值不重要的场合。例如,用作缓冲区的变量通常会被提交给另一个函数进行写操作,覆盖原有内容。由于不会对其进行读操作,所以没有必要将这个变量初始化为某个特定的值。 -慎重使用 `undefined`,如果一个变量是未定义的,使用它出现无法预知的情况。 +<<<@/code/release/define_variable.zig#use-undefined + +::: warning ⚠️ 警告 -当一个变量未定义时,那么它将不会执行默认的初始化操作,此时变量的值将会是无意义的值(我们绝对不能在赋值前使用它)。 +慎重使用 `undefined`:如果一个变量的值是未定义的,那么对这个变量进行读操作时,读取到任何值都是可能的,甚至可能读取到对于这个变量所使用的类型而言完全没有意义的值。 在 `Debug` 模式下,Zig 将 `0xaa` 字节写入未定义的内存。这是为了尽早发现错误,并帮助检测调试器中未定义内存的使用。但是,此行为只是一种实现功能,而不是语言语义,因此不能保证代码可以观察到它。 ::: diff --git a/course/code/12/define_variable.zig b/course/code/12/define_variable.zig index 7bc90fff..71aebadb 100644 --- a/course/code/12/define_variable.zig +++ b/course/code/12/define_variable.zig @@ -15,6 +15,7 @@ pub fn main() !void { DefineVar.main(); Const.main(); Undefined.main(); + UseUndefined.main(); Block.main(); } @@ -79,7 +80,32 @@ const Undefined = struct { // #endregion undefined }; -// #region indentifier +const UseUndefined = struct { + // #region use-undefined + const std = @import("std"); + + // 填充连续递增的数字 + // 注意该函数中并没有对 output 进行读操作,所以 output 的初始值不重要 + fn iota(init: u8, output: []u8) void { + for (output, init..) |*e, v| { + e.* = @intCast(v); + } + } + + pub fn main() void { + // buffer 定义时不需要初始化 + var buffer: [8]u8 = undefined; + + // 因为 iota() 会为 buffer 里的元素赋值 + iota(7, &buffer); + + // 输出 { 7, 8, 9, 10, 11, 12, 13, 14 } + std.debug.print("{any}\n", .{buffer}); + } + // #endregion use-undefined +}; + +// #region identifier const @"identifier with spaces in it" = 0xff; const @"1SmallStep4Man" = 112358; @@ -92,7 +118,7 @@ const Color = enum { @"really red", }; const color: Color = .@"really red"; -// #endregion indentifier +// #endregion identifier const Block = struct { pub fn main() void { diff --git a/course/code/14/define_variable.zig b/course/code/14/define_variable.zig index 7bc90fff..71aebadb 100644 --- a/course/code/14/define_variable.zig +++ b/course/code/14/define_variable.zig @@ -15,6 +15,7 @@ pub fn main() !void { DefineVar.main(); Const.main(); Undefined.main(); + UseUndefined.main(); Block.main(); } @@ -79,7 +80,32 @@ const Undefined = struct { // #endregion undefined }; -// #region indentifier +const UseUndefined = struct { + // #region use-undefined + const std = @import("std"); + + // 填充连续递增的数字 + // 注意该函数中并没有对 output 进行读操作,所以 output 的初始值不重要 + fn iota(init: u8, output: []u8) void { + for (output, init..) |*e, v| { + e.* = @intCast(v); + } + } + + pub fn main() void { + // buffer 定义时不需要初始化 + var buffer: [8]u8 = undefined; + + // 因为 iota() 会为 buffer 里的元素赋值 + iota(7, &buffer); + + // 输出 { 7, 8, 9, 10, 11, 12, 13, 14 } + std.debug.print("{any}\n", .{buffer}); + } + // #endregion use-undefined +}; + +// #region identifier const @"identifier with spaces in it" = 0xff; const @"1SmallStep4Man" = 112358; @@ -92,7 +118,7 @@ const Color = enum { @"really red", }; const color: Color = .@"really red"; -// #endregion indentifier +// #endregion identifier const Block = struct { pub fn main() void {