\当ブログのWordPressテーマはコチラ/クリック

【Zig入門】変数とデータ型

【Zig入門】変数とデータ型

みなさん、こんにちは。システムエンジニアのおみつです。
今回の記事はZigの変数とデータ型に焦点を当て、その基本から応用までを解説します。

目次

変数の基本

変数は、データを保存するための名前付きの箱のようなものです。
Zigでは、変数を宣言する際にはvarキーワードを使用します。

var myVariable: i32 = 10;

このコードでは、i32型呼ばれるデータ型のmyVariableという名前の変数を宣言し、10という値を代入しています。
次の章では様々なデータ型について詳しく解説します。

整数型

Zigには、異なるサイズと符号の整数型が用意されています。
変数に代入されるであろう数値がある程度決まっている場合、その数値にあった整数型を使うようにしましょう。

符号付き整数型

  • i8: -128から127までの値を表現できます。
  • i16: -32,768から32,767までの値を表現できます。
  • i32: -2,147,483,648から2,147,483,647までの値を表現できます。
  • i64: -9,223,372,036,854,775,808から9,223,372,036,854,775,807を表現できます。

符号なし整数型

  • u8: 0から255までの値を表現できます。
  • u16: 0から65,535までの値を表現できます。
  • u32: 0から4,294,967,295の値を表現できます。
  • u64: 0から18,446,744,073,709,551,615の値を表現できます。

何故、整数型のサイズをしっかり意識したほうがいいのかについては以下の記事で詳しく解説しています。是非、読んでみて下さい。

浮動小数点型

次に実数を表現するためのデータ型です。Zigには以下の浮動小数点型があります。

  • f16: 16ビットの浮動小数点数
  • f32: 32ビットの浮動小数点数
  • f64: 64ビットの浮動小数点数

var pi: f32 = 3.141592653589793238;

上記のように、変数を宣言し実数を代入します。

文字と文字列

Zigでは、文字はu8型で、文字列は[]const u8型で表現されます。

var character: u8 = 'A';
var string: []const u8 = "Hello, Zig!";

例えば以下のようなコードがあったとします。

const std = @import("std");
pub fn main() void {
  var character: u8 = 'A';
  var string: []const u8 = "Hello, Zig!";
  std.debug.print("Character: {}\n", .{character});
  std.debug.print("String: {}\n", .{string});
}

実行結果は以下の通りです。

Character: 65
String: Hello, Zig!

以下、同じ文字なのに結果が異なることについて気になるそこのアナタ向けです。
興味のある方は読んでみて下さい。

‘A’は65なのに、Hello, Zig!は文字列として表示されるのはなぜ?

Zigには、他の多くのプログラミング言語のような専用の「文字」型は存在しません。代わりに、Zigでは文字をu8(8ビットの符号なし整数)として表現します。このため、'A'u8型の値65として解釈されます。

文字列に関しても、Zigには専用の「文字列」型は存在しません。代わりに、文字列はバイトの配列、具体的には[]const u8として表現されます。このため、"Hello, Zig!"[]const u8型のバイトの配列として解釈されます。

上記の例では、Zigのstd.debug.print関数で結果をコンソールに表示させています。

単一のu8値を数値として解釈し、その数値を出力します。したがって、'A'はASCII値65として表示されます。

一方、std.debug.print関数は、[]const u8型の配列("Hello, Zig!")を文字列として解釈します。このため、バイトの配列はそのままの文字列として出力されます。

フォーマット文字列の{}プレースホルダは、与えられた引数の型に基づいて動的にフォーマットを適用します。したがって、u8型の値は数値として、[]const u8型の配列は文字列として解釈されます。

この動作は、std.debug.print関数の設計に基づいており、Zigの型システムと組み合わせて、異なる型のデータを適切に表示するためのものです。

ブール型

真または偽の値を持つ型です。Zigのブール型はboolで、trueまたはfalseの値を持ちます。

var isBig: bool = true;
var isSmall: bool = false;

上記の真偽値以外を代入すると、コンパイル時にエラーになります。

厳密にいうとコンパイル時エラーとなるのは、その変数の利用するときです。
宣言するだけでは現時点のZIgコンパイラではエラーをなりません。(2023/08/29執筆時点)

配列

配列は、同じ型のデータを複数持つことができるデータ構造です。

var numbers: [3]i32 = [i32]{1, 2, 3};

このコードでは、i32型のデータを3つ持つ配列numbersを宣言しています。

ポインタ

ポインタは、メモリ上の特定のアドレスを指すデータ型です。ポインタを使用すると、変数のメモリアドレスに直接アクセスしたり、そのアドレスにデータを保存したりすることができます。

少し複雑なのでZigにおけるポインタの宣言と使用について詳しく解説します。

ポインタの宣言

var number: i32 = 10;
var pointerToNumber: *i32 = &number;

ここで、&numberは変数numberのメモリアドレス(10)を取得します。そして、そのアドレスはpointerToNumberという名前のポインタ変数に保存されます。

ポインタを通じた値のアクセス

const valueAtAddress = *pointerToNumber;

*pointerToNumberはポインタをデリファレンスする操作で、これによりポインタが指すアドレスの値にアクセスできます。

つまりこの場合、valueAtAddress10になります。

ポインタを通じた値の変更

*pointerToNumber = 20;

ポインタをデリファレンスして値を変更することで、元の変数の値も変更されます。

つまりこの場合、変数numberの値が20に変更されます。

nullポインタ

var nullPointer: ?*i32 = null;

Zigでは、?を使用してnull可能なポインタを宣言できます。主に次の目的で利用されることが多いです。

  • 初期化
  • 終端マーカー
  • エラーチェック
  • リソースの解放

ポインタの配列

var numbers: [3]i32 = [3]i32{10, 20, 30};
var pointers: [*]i32 = &numbers;

この例では、numbers配列の各要素へのポインタをpointers配列に保存しています。

これらの基本的な操作を理解することで、Zigにおけるポインタの動作と使用方法についての基本的な知識を得ることができます。ポインタは非常に強力なツールであり、メモリの効率的な管理やデータ構造の実装など、多くの高度なタスクに使用されます。

まとめ

この記事では、Zigの変数とデータ型についての基本を解説しました。これらの知識をもとに、Zigでのプログラミングの基礎を固めることができるでしょう。次回は、Zigの演算子について詳しく解説しますので、お楽しみに!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次