0

如果我需要在 Zig 中声明一个结构,我必须在它前面加上一个const

const Arith = struct {
    x: i32,
    y: i32,

    fn add(self: *Arith) i32 {
        return self.x + self.y;
    }
};

test "struct test" {
    var testArith = Arith{
        .x = 9,
        .y = 9,
    };

    expect(testArith.add() == 18);
}

但是它可以以两种方式初始化varconst那么为什么类型声明需要一个常量关键字,而只关心结构的实例是否const存在呢?

4

2 回答 2

4

需要是const因为根范围内的评估顺序是未定义的,并且因为类型变量type只能存在于编译器中(没有内存表示,编译器无法生成它的二进制表示)。但是您可以var在其他范围内使用:

comptime {
   var T = struct { value: u64 };
   
   const x: T = .{ .value = 3 };

   T = struct { ok: bool };

   const y: T = .{ .ok = true };

   @compileLog(x.value); // <- 3
   @compileLog(y.ok); // <- true
}

运行此代码

在其余的答案中,我会详细解释。

常量

const Arith = struct {...};

创建一个推断类型的常量变量。在这种情况下,变量Arith的类型为type

const Arith = struct {...};
comptime {
   @compileLog(@TypeOf(Arith)); // <- type
}

运行此代码


这与将变量声明为:

const Arith: type = struct {...};

变量

您还可以创建一个变量var

例子:

comptime {
   var Arith = struct {...};
}
comptime {
   var Arith: type = struct {...};
}
fn main() !void {
   comptime var Arith = struct {...};
}
fn main() !void {
   var Arith: type = struct {...};
}
fn main() !void {
   comptime var Arith: type = struct {...};
}

因为是一个变量,你可以修改它:

comptime {
   var T = u64;
   T = bool;
   @compileLog(T); // <-- bool
}

运行此代码


Comptime 类型

有些类型只能存在于编译器中,例如:或具有 type或其他 comptime 类型type的字段的结构。anytype

在 的情况下type,这会使编译器解释var x: typecomptime var x: type

然后,考虑以下代码:

var T = struct { value: u64 }; // <- Compiler error

comptime {
   const x: T = .{ .value = 3 };
}
error: variable of type 'type' must be constant

因为根范围内的求值顺序是未定义的,编译器强制在二进制文件中创建一个全局变量,但该类型type没有内存表示。因此,编译器会引发错误。

于 2020-10-27T20:37:44.053 回答
0

由于Arithis 的类型type,它必须被声明为常量,因为编译器期望它是。这可以通过将类型声明更改为此并运行程序来检查

var Arith = struct {
    x: i32,
    y: i32,

    fn add(self: *Arith) i32 {
        return self.x + self.y;
    }
};

这将导致错误 error: variable of type 'type' must be constant

同样在 Zig 中,我们需要一个const或一个var前面的名称,否则它被认为是无效的令牌。

于 2020-10-27T19:59:26.647 回答