🐭
Zigの整数の型変換の組み込み関数を整理しよう
前回の記事でZigの型変換に使う組み込み関数がたくさんでてきた。
いったん整理しよう。今回は整数のみに注目する。
@truncate
@truncate
サイズが小さくなる方に変換するときに使う。
実行時に行われる。
上位のbitが切り取られるので、数値は変化することがある。
@as
@as
コンパイル時に行われる型変換。
サイズが小さくなる方向の変換はコンパイルエラーになる。
変数の場合は自明なので、数値リテラルに明示的に型を与える場面で使われる。
(数値リテラルには型が無いため。これはGo言語と同じ)
(数値リテラルはcomptime_int
という独特の型になっている)
@intCast
@intCast
実行時に行われる型変換。しかしコンパイル時に定数となるものに使われた場合は@asと同じになる。
サイズが小さくなる方向の変換で数値の意味が変わってしまう(変更後のサイズでは表現できない)場合は異常終了となる。
言い方を変えると、@truncateと同様に上位bitの切り取りを行って、切り取ったbit全てが符号ビットと一致しない場合に異常終了する。
@bitCast (2023/01/17修正)
@bitCast
bit幅が同じもの同士での変換。
例えば、f32 -> u32, i32 -> u32 など。
数値を保持するbit列はそのままで、コンパイラがその解釈のみ変更する。
b.zig
const std = @import("std");
const expect = std.testing.expect;
fn func(xa: []const i32) void {
for (xa) |x| {
std.debug.print("x = 0x{0x}, {0d} -> 0x{1x}, {1d}\n", .{x, @bitCast(u32, x)});
}
}
test "bitCast i32 -> u32" {
std.debug.print("\n", .{});
const xa = [_]i32{3, 2, 1, 0, -1, -2, -3};
func(&xa);
}
fn func2(fa: []const f32) void {
for (fa) |f| {
std.debug.print("f = {d} -> 0x{x:0>8}\n", .{f, @bitCast(u32, f)});
}
}
test "bitCast f32 -> u32" {
std.debug.print("\n", .{});
const fa = [_]f32{1.0, 0.0, -1.0, 1.0e-6, 0.15625};
func2(&fa);
}
$ zig test b.zig
Test [1/2] test.bitCast i32 -> u32...
x = 0x3, 3 -> 0x3, 3
x = 0x2, 2 -> 0x2, 2
x = 0x1, 1 -> 0x1, 1
x = 0x0, 0 -> 0x0, 0
x = 0x-1, -1 -> 0xffffffff, 4294967295
x = 0x-2, -2 -> 0xfffffffe, 4294967294
x = 0x-3, -3 -> 0xfffffffd, 4294967293
Test [2/2] test.bitCast f32 -> u32...
f = 1 -> 0x3f800000
f = 0 -> 0x00000000
f = -1 -> 0xbf800000
f = 0.0000009999999974752427 -> 0x358637bd
f = 0.15625 -> 0x3e200000
All 2 tests passed.
関連
Discussion