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
34 changes: 30 additions & 4 deletions course/basic/advanced_type/struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@

:::

## 结构体初始化

在声明了结构体类型之后,我们需要创建该类型的实例。Zig 使用 **结构体字面量(struct literal)** 语法来初始化结构体。

结构体字面量的完整语法是 `StructName{ .field1 = value1, .field2 = value2 }`:

<<<@/code/release/struct.zig#struct_init_basic

以上代码展示了:

- 使用结构体类型名称 `Point` 加上花括号 `{}` 来创建实例
- 花括号内使用 `.字段名 = 值` 的形式为每个字段赋值
- 字段之间用逗号分隔

:::info 🅿️ 提示

结构体字面量中必须为所有没有默认值的字段提供初始值,否则会产生编译错误。

:::

## 自引用

常见的自引用方式是将结构体自身的指针作为函数的第一个参数,例如:
Expand Down Expand Up @@ -79,13 +99,19 @@

:::

## 自动推断
## 类型推断简写

在前面我们学习了结构体字面量的完整语法 `StructName{ .field = value }`。当 Zig 编译器能够从上下文推断出结构体类型时,可以省略类型名称,使用简写语法 `.{ .field = value }`。

这种机制被称为**结果位置语义(Result Location Semantics)**。

Zig 在使用结构体时支持省略类型声明,此时 Zig 会利用结果位置语义进行类型推断,例如:
<<<@/code/release/struct.zig#struct_init_inferred

<<<@/code/release/struct.zig#auto_reference
在上面的示例中:

_这种基于结果位置语义的推导也适用于结构体自身的方法以及其内部定义的其他类型(此处不指结构体字段)。_
- `pt2` 的类型已经被显式声明为 `Point`,因此编译器可以推断出 `.{ .x = 13, .y = 67 }` 应该是 `Point` 类型
- `origin()` 方法的返回类型已声明为 `Point`,因此返回值可以使用简写
- `printPoint` 函数的参数类型为 `Point`,调用时可以直接传入 `.{ .x = 100, .y = 200 }`

## 泛型实现

Expand Down
59 changes: 52 additions & 7 deletions course/code/11/struct.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub fn main() !void {
Struct.main();
StructInitBasic.main();
SelfReference1.main();
SelfReference2.main();
try SelfReference3.main();
AutoReference.main();
StructInitInferred.main();
DefaultField.main();
EmptyStruct.main();
Tuple_.main();
Expand Down Expand Up @@ -172,19 +173,63 @@ const SelfReference3 = struct {
// #endregion more_self_reference3
};

const AutoReference = struct {
const StructInitBasic = struct {
pub fn main() void {
// #region auto_reference
const Point = struct { x: i32, y: i32 };
// #region struct_init_basic
const Point = struct {
x: i32,
y: i32,
};

// 使用完整的结构体字面量语法初始化
const pt1 = Point{ .x = 10, .y = 20 };

// 也可以先声明类型,再使用完整语法初始化
const pt2: Point = Point{ .x = 30, .y = 40 };
// #endregion struct_init_basic

const pt: Point = .{
_ = pt1;
_ = pt2;
}
};

const StructInitInferred = struct {
// #region struct_init_inferred
const Point = struct {
x: i32,
y: i32,

// 在方法返回值中使用简写语法
pub fn origin() Point {
return .{ .x = 0, .y = 0 }; // 返回类型已声明为 Point,可推断
}
};

fn printPoint(p: Point) void {
_ = p;
}

pub fn main() void {
// 完整语法:显式指定类型名称
const pt1 = Point{ .x = 10, .y = 20 };

// 简写语法:当类型可推断时,可省略类型名称
const pt2: Point = .{
.x = 13,
.y = 67,
};
// #endregion auto_reference

_ = pt;
// 在方法返回值中使用简写
const pt3 = Point.origin();

// 作为函数参数传递(参数类型已知时可推断)
printPoint(.{ .x = 100, .y = 200 });

_ = pt1;
_ = pt2;
_ = pt3;
}
// #endregion struct_init_inferred
};

// #region linked_list
Expand Down
59 changes: 52 additions & 7 deletions course/code/12/struct.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub fn main() !void {
Struct.main();
StructInitBasic.main();
SelfReference1.main();
SelfReference2.main();
try SelfReference3.main();
AutoReference.main();
StructInitInferred.main();
DefaultField.main();
EmptyStruct.main();
Tuple_.main();
Expand Down Expand Up @@ -172,19 +173,63 @@ const SelfReference3 = struct {
// #endregion more_self_reference3
};

const AutoReference = struct {
const StructInitBasic = struct {
pub fn main() void {
// #region auto_reference
const Point = struct { x: i32, y: i32 };
// #region struct_init_basic
const Point = struct {
x: i32,
y: i32,
};

// 使用完整的结构体字面量语法初始化
const pt1 = Point{ .x = 10, .y = 20 };

// 也可以先声明类型,再使用完整语法初始化
const pt2: Point = Point{ .x = 30, .y = 40 };
// #endregion struct_init_basic

_ = pt1;
_ = pt2;
}
};

const StructInitInferred = struct {
// #region struct_init_inferred
const Point = struct {
x: i32,
y: i32,

const pt: Point = .{
// 在方法返回值中使用简写语法
pub fn origin() Point {
return .{ .x = 0, .y = 0 }; // 返回类型已声明为 Point,可推断
}
};

fn printPoint(p: Point) void {
_ = p;
}

pub fn main() void {
// 完整语法:显式指定类型名称
const pt1 = Point{ .x = 10, .y = 20 };

// 简写语法:当类型可推断时,可省略类型名称
const pt2: Point = .{
.x = 13,
.y = 67,
};
// #endregion auto_reference

_ = pt;
// 在方法返回值中使用简写
const pt3 = Point.origin();

// 作为函数参数传递(参数类型已知时可推断)
printPoint(.{ .x = 100, .y = 200 });

_ = pt1;
_ = pt2;
_ = pt3;
}
// #endregion struct_init_inferred
};

// #region linked_list
Expand Down
59 changes: 52 additions & 7 deletions course/code/14/struct.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub fn main() !void {
Struct.main();
StructInitBasic.main();
SelfReference1.main();
SelfReference2.main();
try SelfReference3.main();
AutoReference.main();
StructInitInferred.main();
DefaultField.main();
EmptyStruct.main();
Tuple_.main();
Expand Down Expand Up @@ -214,19 +215,63 @@ const SelfReference3 = struct {
// #endregion more_self_reference3
};

const AutoReference = struct {
const StructInitBasic = struct {
pub fn main() void {
// #region auto_reference
const Point = struct { x: i32, y: i32 };
// #region struct_init_basic
const Point = struct {
x: i32,
y: i32,
};

// 使用完整的结构体字面量语法初始化
const pt1 = Point{ .x = 10, .y = 20 };

// 也可以先声明类型,再使用完整语法初始化
const pt2: Point = Point{ .x = 30, .y = 40 };
// #endregion struct_init_basic

_ = pt1;
_ = pt2;
}
};

const StructInitInferred = struct {
// #region struct_init_inferred
const Point = struct {
x: i32,
y: i32,

const pt: Point = .{
// 在方法返回值中使用简写语法
pub fn origin() Point {
return .{ .x = 0, .y = 0 }; // 返回类型已声明为 Point,可推断
}
};

fn printPoint(p: Point) void {
_ = p;
}

pub fn main() void {
// 完整语法:显式指定类型名称
const pt1 = Point{ .x = 10, .y = 20 };

// 简写语法:当类型可推断时,可省略类型名称
const pt2: Point = .{
.x = 13,
.y = 67,
};
// #endregion auto_reference

_ = pt;
// 在方法返回值中使用简写
const pt3 = Point.origin();

// 作为函数参数传递(参数类型已知时可推断)
printPoint(.{ .x = 100, .y = 200 });

_ = pt1;
_ = pt2;
_ = pt3;
}
// #endregion struct_init_inferred
};

// #region linked_list
Expand Down
59 changes: 52 additions & 7 deletions course/code/15/struct.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub fn main() !void {
Struct.main();
StructInitBasic.main();
SelfReference1.main();
SelfReference2.main();
try SelfReference3.main();
AutoReference.main();
StructInitInferred.main();
DefaultField.main();
EmptyStruct.main();
Tuple_.main();
Expand Down Expand Up @@ -214,19 +215,63 @@ const SelfReference3 = struct {
// #endregion more_self_reference3
};

const AutoReference = struct {
const StructInitBasic = struct {
pub fn main() void {
// #region auto_reference
const Point = struct { x: i32, y: i32 };
// #region struct_init_basic
const Point = struct {
x: i32,
y: i32,
};

// 使用完整的结构体字面量语法初始化
const pt1 = Point{ .x = 10, .y = 20 };

// 也可以先声明类型,再使用完整语法初始化
const pt2: Point = Point{ .x = 30, .y = 40 };
// #endregion struct_init_basic

_ = pt1;
_ = pt2;
}
};

const StructInitInferred = struct {
// #region struct_init_inferred
const Point = struct {
x: i32,
y: i32,

const pt: Point = .{
// 在方法返回值中使用简写语法
pub fn origin() Point {
return .{ .x = 0, .y = 0 }; // 返回类型已声明为 Point,可推断
}
};

fn printPoint(p: Point) void {
_ = p;
}

pub fn main() void {
// 完整语法:显式指定类型名称
const pt1 = Point{ .x = 10, .y = 20 };

// 简写语法:当类型可推断时,可省略类型名称
const pt2: Point = .{
.x = 13,
.y = 67,
};
// #endregion auto_reference

_ = pt;
// 在方法返回值中使用简写
const pt3 = Point.origin();

// 作为函数参数传递(参数类型已知时可推断)
printPoint(.{ .x = 100, .y = 200 });

_ = pt1;
_ = pt2;
_ = pt3;
}
// #endregion struct_init_inferred
};

// #region linked_list
Expand Down
Loading
Loading