@intCast

@intCast

정수를 다른 정수로 바꿀 때, 값 자체는 그대로 두고 타입만 바꾸는 내장 함수예요. 반환 타입은 인자로 들어온 타입에서 알아서 추론되구요. 주의할 점은, 목적지 타입의 범위를 벗어나는 숫자를 변환하려고 하면 런타임에 안전 검사에 걸려서 Illegal Behavior로 처리된다는 거예요.

출처: Zig Documentation

본문

@intCast(int: anytype) anytype

@intCast는 정수를 그대로 두고 타입만 다른 정수 타입으로 바꿔요. 수치값은 유지되고, 반환 타입은 문맥에서 추론된 결과 타입이에요. 만약 목적지 타입의 범위를 벗어나는 값을 변환하려고 하면, 안전 검사에 걸린 Illegal Behavior가 발생해요.

실제로 어떤 일이 벌어지는지 예시로 볼게요. 아래 테스트는 u16 값을 u8로 변환하면서 패닉이 나는 상황을 보여줘요.

test "integer cast panic" {
    var a: u16 = 0xabcd; // runtime-known
    _ = &a;
    const b: u8 = @intCast(a);
    _ = b;
}
$ zig test test_intCast_builtin.zig
1/1 test_intCast_builtin.test.integer cast panic...thread 973185 panic: integer does not fit in destination type
/home/ci/work/zig-bootstrap/zig/doc/langref/test_intCast_builtin.zig:4:19: 0x1253930 in test.integer cast panic (test_intCast_builtin.zig)
    const b: u8 = @intCast(a);
                  ^
/home/ci/work/zig-bootstrap/out/host/lib/zig/compiler/test_runner.zig:295:25: 0x1207381 in mainTerminal (test_runner.zig)
        if (test_fn.func()) |_| {
                        ^
/home/ci/work/zig-bootstrap/out/host/lib/zig/compiler/test_runner.zig:74:28: 0x1206b52 in main (test_runner.zig)
        return mainTerminal(init);
                           ^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:789:88: 0x12032af in callMain (std.zig)
    if (fn_info.param_types[0].? == std.process.Init.Minimal) return wrapMain(root.main(.{
                                                                                       ^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:248:5: 0x1202c81 in _start (std.zig)
    asm volatile (switch (native_arch) {
    ^
error: the following test command terminated with signal ABRT:
/home/ci/work/zig-bootstrap/out/zig-local-cache/o/a832d88372c85f4e7ac55ce034124718/test --seed=0x5930ef66

au16인데 값이 컴파일 타임에 정해지지 않고 런타임에 정해져요(주석의 runtime-known). 그 실행 값 0xabcdu8 범위를 벗어나니까 @intCast가 패닉을 일으키는 거죠. "integer does not fit in destination type"이라는 메시지가 바로 그 안전 검사가 작동했다는 신호예요.

만약 범위를 벗어난 숫자의 유효 비트를 잘라내고 싶다면 @truncate를 쓰세요.

그리고 Tcomptime_int라면, 이 변환은 Type Coercion과 의미상 같아져요.

더 알아보기

  • @truncate — 범위를 벗어난 숫자의 유효 비트를 자를 때 써요.
  • Type Coercioncomptime_int가 관련될 때 @intCast와 동일한 의미.
  • Illegal Behavior — 안전 검사에 걸렸을 때 일어나는 동작.