ざっくりZig - 変数の値を変更 (var, null, undefined)

2024/03/18に公開

値を変更できない代入、値を変更できる代入

const a = 1;      // 代入した後は値を変更できない
var a: u8 = 1;    // 代入した後も値を変更できる

constで変数に値を代入すると、そのあとは値を変更できません。

const a = 1;
// a = 2;         エラー

varで変数に値を代入すると、そのあとも値を変更できます。ただし、このとき変数の型を宣言する必要があります。varで代入された変数の値が処理の最後まで全く変更されないとエラーとなります。

// var a = 1;     エラー
var a: u8 = 1;    // 最後まで値を変更しないとエラー
a = 2;            // 値を変更できる

値の変更と代入を同時に行う演算子

変数の値をもとに計算した結果を同じ変数に代入しなおす演算子が用意されています。演算子の文字は途中に空白を入れず、すべて連続していなくてはなりません。

演算子 内容
+= a += 1 aの値を1増やす
+|= a +| = 1 aの値を1増やし飽和演算
+%= a +%= 1 aの値を1増やしラップアラウンド
-= a -= = 1 aの値を1減らす
-|= a -| = 1 aの値を1減らし飽和演算
-%= a -% = 1 aの値を1減らしラップアラウンド
*= a *= 2 aの値を2倍する
*|= a *|= 2 aの値を2倍して飽和演算
*%= a *%= 2 aの値を2倍してラップアラウンド
/= a /= 2 aの値を半分にする
%= a %= 2 aの値を2で割った余りとする
<<= a <<= 1 aの値を1ビット左シフトした値にする
<<|= a <<| = 1 aの値を1ビット左シフトして飽和演算
&= a &= 0b11111011 aの右から3ビット目を0にする
|= a |= 0b00000100 aの右から3ビット目を1にする
^= a ^= 0b00000100 aの値をxorで演算した値にする

四則演算、ラップアラウンド、飽和演算の比較

変数の値を+1, -1していくだけなら値の変化は単純ですが、ラップアラウンドや飽和演算になると、変数に宣言された型によって、どのタイミングでどんな値になるかがそれぞれ異なります。

var a: u8 = 254;
a += 1;     // a = 255
// a += 1;     (正の)オーバーフロー

a +| = 1;   // a = 255;     u8型での飽和演算なのでこれ以上増えない
a +%= 1;    // a = 0;       u8型でのラップアラウンドなので255 + 1は0になる

var b: i8 = -127
b -= 1;     // b = -128
//  b -= 1;    (負の)オーバーフロー
b -|= 1;    // b = -128     i8型での飽和演算なので、これ以上減らない
b -% = 1;   // b = 127      i8型でのラップアラウンドなので-128 - 1は127になる

オプションの設定

変数には1などの値のほかに、何もないことを示す null を代入できる オプション を設定できます。これは型名の前に ? をつけます。

var a: ?u8 = null;  // u8型にオプションを設定した

オプションが設定された変数から値を取得する方法は .?orelse の2通りあります。

var a: ?u8 = null;
a = 1;      // null以外の値に変更
a.?         // aの値を取得し、nullのときはエラー
a = null    // aの値をnullに変更
a orelse 0  // aの値は0 (aがnullのときは0、それ以外ならaの値のまま)

オプションが設定された変数の値を標準出力に出力するときは、値を取得する方法に合わせた書式があります。

const std = @import("std");
const stdout = std.io.getStdOut().writer();

// ........

try stdout.print("{}", .{a.?});   // aの値がnullのときはエラー
try stdout.print("{?}", .{a});    // aの値がnullのときは"null"となる
try stdout.print("{?d}", .{a});   // aの書式をより明確にするとき
try stdout.print("{}", .{a orelse 0});   // このときは{}で出力可能

初期設定で未定義とする

変数を初期設定するときなど、特に値を定義しないことを示す undefiend を設定できます。変数の設定をまとめて行うときに便利です。

var a: u8 = undefined;  // 初期設定では未定義
a = 1;  // 変数を使用するときに値を設定

まとめ

  • varで変数に値を代入すると、そのあとに変数の値を変更できる。変更しないとエラーとなる。
  • +=, -=など変数の値を使用して計算した値に変更する演算子が用意されている。
    (飽和演算やラップアラウンドの計算はどのタイミングでどんな値に変更されるのか注意)
  • 変数には「?型名」という オプション を設定できる。これにより変数に何もないことを示すnullを代入できる。このとき変数の値は 変数名.? で取得するか、もしくは orelse で変数の値がnullのときの値を設定する
  • オプションが設定された変数の値を標準出力に出力するときは値を取得する方法に応じて書式を{}, {?}, {?詳細な書式}のいずれかにする。
  • 変数の初期設定などで値を定義しない undefined を代入できる。

判断と振り分け (if, switch) >
< ビット幅と演算
ざっくりZig 一覧

Discussion