Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e54141256 | ||
|
|
13b7831862 | ||
|
|
5310ceb04b | ||
|
|
1d4986ac07 | ||
|
|
826f745917 | ||
|
|
a05ebe9ff8 | ||
|
|
2eab522da9 |
@@ -9,7 +9,7 @@ by [Karl Seguin](https://github.com/karlseguin) into Russian.
|
||||
Distributed under the terms of
|
||||
[Attribution-NonCommercial-ShareAlike 4.0 International](http://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
|
||||
# Converting from `md` to
|
||||
# Converting from `md` to other formats
|
||||
|
||||
## epub
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
На [этой странице](https://ziglang.org/download/) вы можете загрузить
|
||||
скомпилированные файлы для различных программно-аппаратных платформ. Там
|
||||
есть как и уже выпущенные версии (на данный момент самая свежая
|
||||
это`0.11.0`), так и слепок текущей разрабатываемой. Загрузите подходящую
|
||||
это`0.12.0`), так и слепок текущей разрабатываемой. Загрузите подходящую
|
||||
для вас версию и просто разверните архив в какое-то удобное для вас
|
||||
место, сделайте ссылку на файл `zig` (или добавьте псевдоним, или
|
||||
добавьте нужный путь в переменную `PATH`, как вам удобнее).
|
||||
|
||||
@@ -149,7 +149,7 @@ i32@7ffdb6cad4e0
|
||||
адрес второго поля ровно на 8 байт больше.
|
||||
|
||||
Оператор взятия адреса возвращает *указатель* на значение. Это другой
|
||||
тип, не такой же, как у самого значение. Указатель на значение типа `T`
|
||||
тип, не такой же, как у самого значения. Указатель на значение типа `T`
|
||||
пишется как `*T`. Следовательно, когда мы берём адрес переменной `user`,
|
||||
он будет иметь тип `*User`, то есть указатель на `User`:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
Рассмотрение указателей в предыдущей главе ознакомило нас с взаимосвязью
|
||||
между переменными, данными и памятью. Но нам ещё нужно поговорить о том,
|
||||
как происходит управление ланными и памятью. Для коротко-живущих и
|
||||
как происходит управление данными и памятью. Для коротко-живущих и
|
||||
простых скриптов это, как правило, не имеет особого значения. В наше
|
||||
время, имея ноутбук, оснащённый 32-мя гигабайтами оперативной памяти, вы
|
||||
можете запустить свою программу, которая, делая какую-то работу
|
||||
|
||||
23
src/ch08.md
23
src/ch08.md
@@ -217,11 +217,10 @@ const Writer = struct {
|
||||
const gen = struct {
|
||||
pub fn writeAll(pointer: *anyopaque, data: []const u8) anyerror!void {
|
||||
const self: T = @ptrCast(@alignCast(pointer));
|
||||
return ptr_info.Pointer.child.writeAll(self, data);
|
||||
return ptr_info.pointer.child.writeAll(self, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return .{
|
||||
.ptr = ptr,
|
||||
.writeAllFn = gen.writeAll,
|
||||
@@ -289,18 +288,18 @@ union), которая полностью описывает тип. Далее
|
||||
возможности Zig по генерации исходного кода во время компиляции.
|
||||
|
||||
Последняя часть этого кода это вызов функции посредством
|
||||
`ptr_info.Pointer.child.writeAll(self, data)`. Встроенная функция
|
||||
`ptr_info.pointer.child.writeAll(self, data)`. Встроенная функция
|
||||
`@@typeInfo(T)` возвращает `std.builtin.Type`, а это, как уже было
|
||||
отмечено, маркированная объединение, которое описывает тот или иной тип.
|
||||
Оно может описывать 24 разновидности типов, как то целые числа,
|
||||
необязательные значения, структуры, указатели и т.д. Каждый тип имеет
|
||||
необязательные значения, структуры, указатели и т.д. Каждый тип имеет
|
||||
свои особенные свойства. Так, целые числа обладают "знаковостью"
|
||||
(`signedness`), в то время как другие типы такого свойства не имеют. Вот
|
||||
так выглядит `@typeInfo(*File)`:
|
||||
|
||||
```zig
|
||||
builtin.Type{
|
||||
.Pointer = builtin.Type.Pointer{
|
||||
.pointer = builtin.Type.Pointer{
|
||||
.address_space = builtin.AddressSpace.generic,
|
||||
.alignment = 4,
|
||||
.child = demo.File,
|
||||
@@ -308,14 +307,14 @@ builtin.Type{
|
||||
.is_const = false,
|
||||
.is_volatile = false,
|
||||
.sentinel = null,
|
||||
.size = builtin.Type.Pointer.Size.One
|
||||
.size = builtin.Type.Pointer.Size.one
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Поле `child` это фактический тип сущности, на которую показывает
|
||||
указатель. Когда мы вызываем `init`, передавая ей `*File`,
|
||||
`ptr_info.Pointer.child.writeAll(...)` транслируется в
|
||||
`ptr_info.pointer.child.writeAll(...)` транслируется в
|
||||
`File.writeAll(...)`, то есть получается именно то, что мы и хотели.
|
||||
|
||||
Если вы посмотрите на другие применения такой витиеватой схемы,
|
||||
@@ -323,8 +322,8 @@ builtin.Type{
|
||||
получения информации о типе:
|
||||
|
||||
```zig
|
||||
if (ptr_info != .Pointer) @compileError("ptr must be a pointer");
|
||||
if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single item pointer");
|
||||
if (ptr_info != .pointer) @compileError("ptr must be a pointer");
|
||||
if (ptr_info.pointer.size != .one) @compileError("ptr must be a single item pointer");
|
||||
```
|
||||
|
||||
Таким образом делаются дополнительные проверки во время компиляции,
|
||||
@@ -334,13 +333,13 @@ if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single item poin
|
||||
Также вместо вызова функции посредством
|
||||
|
||||
```zig
|
||||
ptr_info.Pointer.child.writeAll(self, data);
|
||||
ptr_info.pointer.child.writeAll(self, data);
|
||||
```
|
||||
|
||||
можно встретить такое
|
||||
|
||||
```zig
|
||||
@call(.always_inline, ptr_info.Pointer.child.writeAll, .{self, data});
|
||||
@call(.always_inline, ptr_info.pointer.child.writeAll, .{self, data});
|
||||
```
|
||||
|
||||
Вызов функции напрямую (как мы это и делали) по сути ничем не отличается
|
||||
@@ -358,7 +357,7 @@ ptr_info.Pointer.child.writeAll(self, data);
|
||||
|
||||
## Использование маркированных объединений
|
||||
|
||||
В качестве более простой альтернативы описанным схемам для эмуляции
|
||||
В качестве более простой альтернативы описанным схемам для эмуляции
|
||||
интерфейсов можно применять маркированные объединения, вот полноценный
|
||||
рабочий пример:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
const a = [_]i32{1, 2, 3, 4, 5};
|
||||
var end: usize = 4;
|
||||
const end: usize = 4;
|
||||
const b = a[1..end];
|
||||
std.debug.print("{any}\n", .{@TypeOf(b)});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
var user = User{
|
||||
// var user = User{ // zig 0.11
|
||||
const user = User{ // zig 0.12
|
||||
.id = 1,
|
||||
.power = 100,
|
||||
};
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
var user = User{
|
||||
// var user = User{ // 0.11
|
||||
const user = User{ // 0.12
|
||||
.id = 1,
|
||||
.power = 100,
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
var user1 = User.init(1, 10);
|
||||
var user2 = User.init(2, 20);
|
||||
const user1 = User.init(1, 10);
|
||||
const user2 = User.init(2, 20);
|
||||
|
||||
std.debug.print("User {d} has power of {d}\n", .{user1.id, user1.power});
|
||||
std.debug.print("User {d} has power of {d}\n", .{user2.id, user2.power});
|
||||
|
||||
@@ -5,7 +5,7 @@ pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var arr = try allocator.alloc(usize, 4);
|
||||
const arr = try allocator.alloc(usize, 4);
|
||||
allocator.free(arr);
|
||||
allocator.free(arr);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
const std = @import("std");
|
||||
const os = std.os;
|
||||
//const os = std.os; // 0.11
|
||||
const posix = std.posix; // 0.12
|
||||
|
||||
const Writer = union(enum) {
|
||||
file: File,
|
||||
@@ -13,10 +14,10 @@ const Writer = union(enum) {
|
||||
};
|
||||
|
||||
const File = struct {
|
||||
fd: os.fd_t,
|
||||
fd: posix.fd_t,
|
||||
|
||||
fn writeAll(self: File, data: []const u8) !void {
|
||||
_ = try std.os.write(self.fd, data);
|
||||
_ = try std.posix.write(self.fd, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ pub fn build(b: *std.Build) !void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const calc_module = b.addModule("calc", .{
|
||||
.source_file = .{ .path = "calc/calc.zig" },
|
||||
.root_source_file = .{ .path = "calc/calc.zig" },
|
||||
});
|
||||
|
||||
// setup executable
|
||||
@@ -16,7 +16,8 @@ pub fn build(b: *std.Build) !void {
|
||||
.optimize = optimize,
|
||||
.root_source_file = .{ .path = "program.zig" },
|
||||
});
|
||||
exe.addModule("calc", calc_module);
|
||||
//exe.addModule("calc", calc_module);
|
||||
exe.root_module.addImport("calc", calc_module);
|
||||
b.installArtifact(exe);
|
||||
|
||||
// run step
|
||||
@@ -31,7 +32,8 @@ pub fn build(b: *std.Build) !void {
|
||||
.optimize = optimize,
|
||||
.root_source_file = .{ .path = "program.zig" },
|
||||
});
|
||||
tests.addModule("calc", calc_module);
|
||||
//tests.addModule("calc", calc_module);
|
||||
tests.root_module.addImport("calc", calc_module);
|
||||
|
||||
const test_cmd = b.addRunArtifact(tests);
|
||||
test_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
Reference in New Issue
Block a user