Skip to content
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ bun dev # 启动热更开发服务
- 等待 Review
- 合并到上游仓库,并由 GitHub Action 自动构建

**开发命令:**
**开发命令**

```sh
bun i # 安装依赖
Expand All @@ -61,4 +61,4 @@ bun run preview # 运行预览
> [!NOTE]
> 本文档所使用的构建工具为 [bunjs](https://bun.sh/),在提交时请勿将其他 nodejs 的包管理工具的额外配置文件添加到仓库中。

> 如需要更新依赖,请参照此处 [Lockfile](https://bun.sh/docs/install/lockfile) 先设置 git 使用 bun 来 diff 文件!
> 如需要更新依赖,请参照此处 [Lockfile](https://bun.sh/docs/install/lockfile) 先设置 git 使用 bun 来 diff 文件!
8 changes: 4 additions & 4 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"@giscus/vue": "^3.1.1",
},
"devDependencies": {
"@types/node": "^24.0.7",
"prettier": "^3.6.0",
"@types/node": "^24.0.10",
"prettier": "^3.6.2",
"vitepress": "^1.6.3",
"vitepress-export-pdf": "^1.0.0",
},
Expand Down Expand Up @@ -204,7 +204,7 @@

"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],

"@types/node": ["@types/node@24.0.7", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw=="],
"@types/node": ["@types/node@24.0.10", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA=="],

"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],

Expand Down Expand Up @@ -548,7 +548,7 @@

"preact": ["preact@10.20.1", "", {}, "sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw=="],

"prettier": ["prettier@3.6.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw=="],
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],

"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],

Expand Down
4 changes: 2 additions & 2 deletions course/advanced/assembly.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ outline: deep
3. 内核的开发,现代化内核编写时均会使用汇编来完成一些初始化工作,如 bootloader,分段分页,中断处理等。
4. 程序的优化,高级语言的编译器并不是完美的,它有时会做出反而使程序变慢的“优化”,而汇编语言完全由程序员控制。

zig 中使用汇编有两种方式,引入外部的内联汇编,内联汇编大概是使用最多的情况
Zig 中使用汇编有两种主要方式:外部汇编和内联汇编。内联汇编是更常用的方式

::: info 🅿️ 提示

Expand Down Expand Up @@ -47,7 +47,7 @@ outline: deep

## 内联汇编

内联汇编给予了我们可以将 `low-level` 的汇编代码和高级语言相组合,实现更加高效或者更直白的操作
内联汇编允许我们将底层汇编代码与高级语言相结合,以实现更高效或更直接的操作

<<<@/code/release/assembly.zig#inline_assembly

Expand Down
40 changes: 20 additions & 20 deletions course/basic/advanced_type/array.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,94 +4,94 @@ outline: deep

# 数组

数组是日常敲代码使用相当频繁的类型之一,在 zig 中,数组的分配和 C 类似,均是在内存中连续分配且固定数量的相同类型元素
数组是日常编程中使用相当频繁的数据类型之一,在 Zig 中,数组的内存分配方式与 C 类似:在内存中连续分配固定数量的相同类型的元素

因此数组有以下三点特性
因此,数组具有以下三个特性

- 长度固定
- 元素必须有相同的类型
- 依次线性排列

## 创建数组

zig 中,你可以使用以下的方法,来声明并定义一个数组
Zig 中,你可以使用以下方式来声明并定义一个数组

<<<@/code/release/array.zig#create_array

以上代码展示了定义一个字面量数组的方式,其中你可以选择指明数组的大小或者使用 `_` 代替。使用 `_` 时,zig 会尝试自动计算数组的长度
以上代码展示了如何定义一个字面量数组。其中,你可以明确指定数组的大小,也可以使用 `_` 让 Zig 自动推断数组的长度

数组元素是连续放置的,故我们可以使用下标来访问数组的元素,下标索引从 `0` 开始
数组元素是连续存放的,因此我们可以通过下标来访问数组元素。下标索引从 `0` 开始

关于[越界问题](https://ziglang.org/documentation/master/#Index-out-of-Bounds),zig 在编译期和运行时均有完整的越界保护和完善的堆栈错误跟踪
关于[越界问题](https://ziglang.org/documentation/master/#Index-out-of-Bounds),Zig 在编译期和运行时都提供了完整的越界保护和完善的堆栈错误跟踪

### 解构数组

我们在变量声明的章节提到了,数组可以结构,再来回忆一下
我们在变量声明的章节中提到过,数组可以被解构。让我们回顾一下

<<<@/code/release/array.zig#deconstruct

### 多维数组

多维数组(矩阵)实际上就是嵌套数组,我们很容易就可以创建一个多维数组出来
多维数组(矩阵)实际上就是嵌套的数组。我们可以很容易地创建一个多维数组

<<<@/code/release/array.zig#matrix

在以上的示例中,我们使用了 [for](/basic/process_control/loop) 循环,来进行矩阵的打印,关于循环我们放在后面再聊
在以上示例中,我们使用了 [for](/basic/process_control/loop) 循环来打印矩阵。关于循环的更多细节,我们将在后续章节讨论

## 哨兵数组(标记终止数组)

> 很抱歉,这里的名字是根据官方的文档直接翻译过来的,原文档应该是 ([Sentinel-Terminated Arrays](https://ziglang.org/documentation/master/#toc-Sentinel-Terminated-Arrays))
> 该名称直接翻译自官方文档的 ([Sentinel-Terminated Arrays](https://ziglang.org/documentation/master/#toc-Sentinel-Terminated-Arrays))。

:::info

本质上来说,这是为了兼容 C 中的规定的字符串结尾字符`\0`
其本质是为了兼容 C 语言中以 `\0` 作为结尾的字符串。

:::

我们使用语法 `[N:x]T` 来描述一个元素为类型 `T`,长度为 `N` 的数组,在它对应 `N` 的索引处的值应该是 `x`。前面的说法可能比较复杂,换种说法,就是这个语法表示数组的长度索引处的元素应该是 `x`,具体可以看下面的示例
我们使用 `[N:x]T` 语法来定义一个哨兵数组。它表示一个长度为 `N`、元素类型为 `T` 的数组,并且在索引 `N` 处的值固定为 `x`。换言之,在数组末尾有一个值为 `x` 的哨兵元素。请看下面的示例

<<<@/code/release/array.zig#terminated_array

:::info 🅿️ 提示

注意:只有在使用哨兵时,数组才会有索引为数组长度的元素
注意:只有哨兵数组才能访问到索引为数组长度的元素

:::

## 操作

:::info

以下操作都是编译期 (comptime) 的,如果你需要运行时地处理数组操作,请使用 `std.mem`。
以下操作都是在编译期(comptime)执行的。如果需要在运行时处理数组,请使用 `std.mem`。

:::

### 乘法

可以使用 `**` 对数组做乘法操作,运算符左侧是数组,右侧是倍数,进行矩阵的叠加
可以使用 `**` 对数组进行乘法操作。运算符左侧是数组,右侧是重复的次数,最终会生成一个更长的数组

<<<@/code/release/array.zig#multiply

### 串联

数组之间可以使用 `++` 进行串联操作(编译期),只要两个数组的元素类型相同,它们就可以串联!
可以使用 `++` 在编译期对数组进行串联。只要两个数组的元素类型相同,它们就可以被连接起来。

<<<@/code/release/array.zig#connect

## 奇技淫巧

受益于 zig 自身的语言特性,我们可以实现某些其他语言所不具备的方式来操作数组
得益于 Zig 独特的语言特性,我们可以用一些在其他语言中不常见的方式来操作数组

### 使用函数初始化数组

可以使用函数来初始化数组,函数要求返回一个数组的元素或者一个数组
我们可以使用函数来初始化数组。该函数需要返回数组的单个元素或整个数组

<<<@/code/release/array.zig#func_init_array

### 编译期初始化数组

通过编译期来初始化数组,以此来抵消运行时的开销!
我们可以在编译期初始化数组,从而避免运行时的开销。

<<<@/code/release/array.zig#comptime_init_array

这个示例中,我们使用了编译期的功能,来帮助我们实现这个数组的初始化,同时还利用了 `blocks` 和 `break` 的性质,关于这个我们会在 [循环](/basic/process_control/loop) 讲解!
在这个示例中,我们利用编译期执行的特性来初始化数组,并结合了 `blocks` 和 `break` 的用法。关于这些,我们将在[循环](/basic/process_control/loop)章节中详细讲解。
34 changes: 17 additions & 17 deletions course/basic/advanced_type/enum.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ outline: deep

# 枚举

> 枚举常常用来列出一个有限集合的任何成员,或者对某一种特定对象的计数
> 枚举常用于表示一个有限集合的成员,或对特定类型的对象进行分类

枚举是一种相对简单,但用处颇多的类型
枚举是一种相对简单但用途广泛的类型

## 声明枚举

我们可以通过使用 `enum` 关键字来很轻松地声明并使用枚举
我们可以通过 `enum` 关键字轻松地声明和使用枚举

<<<@/code/release/enum.zig#basic_enum

同时,zig 还允许我们访问并操作枚举的标记值
同时,Zig 还允许我们访问和操作枚举的标记值

<<<@/code/release/enum.zig#enum_with_value

Expand All @@ -24,33 +24,33 @@ outline: deep

::: info 🅿️ 提示

枚举类型支持使用 `if` 和 `switch` 进行匹配,具体见对应章节
枚举类型支持使用 `if` 和 `switch` 进行匹配,具体细节请参见相应章节

:::

## 枚举方法

没错,枚举也可以拥有方法,实际上枚举仅仅是一种命名空间(你可以看作是一类 struct)。
是的,枚举也可以拥有方法。实际上,枚举在 Zig 中是一种特殊的命名空间(可以看作一种特殊的 `struct`)。

<<<@/code/release/enum.zig#enum_with_method

## 枚举大小

要注意的是,枚举的大小是会经过 zig 编译器进行严格的计算,如以上的枚举类型 `Type` ,它大小等效于 `u1`。
需要注意的是,Zig 编译器会严格计算枚举的大小。例如,前面示例中的 `Type` 枚举,其大小等效于 `u1`。

以下示例中,我们使用了内建函数 `@typeInfo` 和 `@tagName` 来获取枚举的大小和对应的 tag name:
以下示例中,我们使用了内建函数 `@typeInfo` 和 `@tagName` 来获取枚举的大小和对应的标签名称(tag name

<<<@/code/release/enum.zig#enum_size

## 枚举推断

枚举也支持让 zig 编译器自动进行推断(使用结果位置语义),即在已经知道枚举的类型情况下仅使用字段来指定枚举的值
枚举也支持类型推断(通过结果位置语义),即在已知枚举类型的情况下,可以仅使用字段名来指定枚举值

<<<@/code/release/enum.zig#enum_reference

## 非详尽枚举

zig 允许我们不列出所有的枚举值,未列出枚举值可以使用 `_` 代替。由于未列出枚举值的存在,枚举的大小无法自动推断,必须显式指定
Zig 允许我们定义非详尽枚举,即在定义时无需列出所有可能的成员。未列出的成员可以使用 `_` 来表示。由于存在未列出的成员,编译器无法自动推断枚举的大小,因此必须显式指定其底层类型

<<<@/code/release/enum.zig#non_exhaustive_enum

Expand All @@ -68,25 +68,25 @@ zig 允许我们不列出所有的枚举值,未列出枚举值可以使用 `_`

::: info 🅿️ 提示

此部分内容并非是初学者需要掌握的内容,它涉及到 zig 本身的类型系统和 [编译期反射](../../advanced/reflection#构建新的类型),可以暂且跳过!
此部分内容并非初学者需要掌握的内容,它涉及到 Zig 的类型系统和[编译期反射](../../advanced/reflection#构建新的类型),可以暂且跳过!

:::

zig 还包含另外一个特殊的类型 `EnumLiteral`,它是 [`std.builtin.Type`](https://ziglang.org/documentation/master/std/#std.builtin.Type) 的一部分。
Zig 还包含一个特殊的类型 `EnumLiteral`,它是 [`std.builtin.Type`](https://ziglang.org/documentation/master/std/#std.builtin.Type) 的一部分。

可以将它称之为“枚举字面量”它是一个与 `enum` 完全不同的类型可以查看 zig 类型系统对 `enum` 的 [定义](https://ziglang.org/documentation/master/std/#std.builtin.Type.Enum),并不包含 `EnumLiteral`
我们可以称之为“枚举字面量”它是一个与 `enum` 完全不同的类型可以查看 Zig 类型系统对 `enum` 的[定义](https://ziglang.org/documentation/master/std/#std.builtin.Type.Enum),其中并不包含 `EnumLiteral`

它的具体使用如下
它的具体用法如下

<<<@/code/release/enum.zig#enum_literal

注意:此类型常用于作为函数参数!
注意:此类型常用于函数参数。

## extern

注意,我们不在这里使用 `extern` 关键字。
注意,我们通常不直接对枚举使用 `extern` 关键字。

默认情况下,zig 不保证枚举和 C ABI 兼容,但是我们可以通过指定标记类型来达到这一效果
默认情况下,Zig 不保证枚举与 C ABI 兼容,但我们可以通过指定其标记类型来确保兼容性

```zig
const Foo = enum(c_int) { a, b, c };
Expand Down
8 changes: 4 additions & 4 deletions course/basic/advanced_type/opaque.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ outline: deep

# opaque

`opaque` 类型声明一个具有未知(但非零)大小和对齐方式的新类型,它的内部可以包含与结构、联合和枚举相同的声明
`opaque` 类型用于声明一个大小和对齐方式未知(但非零)的新类型。其内部可以像结构体、联合或枚举一样包含声明

这通常用于保证与不公开结构详细信息的 C 代码交互时的类型安全
这通常用于与 C 代码交互时,确保类型安全,尤其是在 C 代码没有公开结构体细节的情况下

<<<@/code/release/opaque.zig#opaque

## anyopaque

`anyopaque` 是一个比较特殊的类型,代表可以接受任何类型的 `opaque`(由于 `opaque` 拥有不同的变量/常量声明和方法的定义,故是不同的类型),常用于与 C 交互的函数中,可以当作 C 的 `void` 类型来使用,一般用于类型擦除指针!
`anyopaque` 是一个特殊的类型,它可以代表任意一种 `opaque` 类型(因为每个 `opaque` 类型根据其内部声明的不同而被视为不同类型)。它常用于与 C 交互的函数中,类似于 C 的 `void*`,通常用于类型擦除的指针。

:::info 🅿️ 提示

需要注意,`void` 的已知大小为 0 字节,而 `anyopaque` 大小未知,但非零
需要注意的是,`void` 的大小为 0 字节,而 `anyopaque` 的大小未知但非零

:::

Expand Down
Loading
Loading