Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

改进关于 undefined 的说明 #188

Merged
merged 1 commit into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions course/basic/define-variable.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ outline: deep

如果一定要使用不符合这些规定的名称(例如与外部库的链接),那么请使用 `@""` 语法。

<<<@/code/release/define_variable.zig#indentifier
<<<@/code/release/define_variable.zig#identifier

::: info 🅿️ 提示

Expand All @@ -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` 字节写入未定义的内存。这是为了尽早发现错误,并帮助检测调试器中未定义内存的使用。但是,此行为只是一种实现功能,而不是语言语义,因此不能保证代码可以观察到它。
:::
Expand Down
30 changes: 28 additions & 2 deletions course/code/12/define_variable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn main() !void {
DefineVar.main();
Const.main();
Undefined.main();
UseUndefined.main();
Block.main();
}

Expand Down Expand Up @@ -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;

Expand All @@ -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 {
Expand Down
30 changes: 28 additions & 2 deletions course/code/14/define_variable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn main() !void {
DefineVar.main();
Const.main();
Undefined.main();
UseUndefined.main();
Block.main();
}

Expand Down Expand Up @@ -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;

Expand All @@ -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 {
Expand Down