WTF Solidity 超シンプル入門:配列(Array)と構造体(Struct)の完全ガイド
【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程,供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity
本記事は、WTF Solidity 超シンプル入門の第6講「配列(Array)と構造体(Struct)」を、日本語版レッスン(Languages/ja/06_ArrayAndStruct_ja/readme.md)と実際のサンプルコード(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol)に基づいて解説する技術ガイドです。この講義を読み終えると、Solidity でデータの集合を扱う2つの重要な参照型——固定長・可変長配列の宣言と操作(length/push/pop)、そして構造体structの定義と4通りの値代入方法——を、ガス消費の観点も含めて実践的に使いこなせるようになります。
このレッスンは、データの格納場所(storage/memory/calldata)を扱う前回の第5講(データの格納場所)の続きにあたります。配列や構造体は「参照型」であり、その振る舞いはデータの格納場所に大きく依存するため、まだの方は先に第5講を確認しておくと理解がスムーズです。
1. 配列(Array)の基本
array(配列)は Solidity でデータ(整数、バイト、アドレスなどの集合)を格納するためによく使われる変数型です。配列には固定長配列と可変長配列(動的配列)の2種類があります。
1.1 固定長配列
固定長配列は宣言時に配列の長さを指定します。T[k]というフォーマットで宣言し、Tは要素の型、kは長さを表します。
// 固定長配列(fixed-length array) uint[8] array1; bytes1[5] array2; address[100] array3;1.2 可変長配列(動的配列)
可変長配列は宣言時に長さを指定しません。T[]というフォーマットで宣言し、Tは要素の型を表します。宣言後に長さを変更できるのが特徴です。
// 可変長配列(variable-length array) uint[] array4; bytes1[] array5; address[] array6; bytes array7;1.3bytesの特殊性:byte[]は使えない
bytesは特別なケースです。bytes自体が動的配列ですが、[]を付ける必要がありません。単一バイトの配列を宣言する場合、bytesかbytes1[]を使用できますが、byte[]は使用できません。また、bytesはbytes1[]よりも少ないガスを消費するため、Solidity 公式でも推奨されています。
実際のサンプルコード(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L5-L14)でも、この宣言パターンがそのまま確認できます。
// 固定長配列 uint[8] array1; bytes1[5] array2; address[100] array3; // 可変長配列 uint[] array4; bytes1[] array5; address[] array6; bytes array7;2. 配列を作成する際のルール
Solidity で配列を作成する際には、いくつかの重要なルールがあります。
2.1memory動的配列はnew演算子で作成する
memory修飾子が付いた動的配列は、new演算子を使って作成できます。ただし、必ず長さを宣言する必要があり、宣言した後に長さを変更することはできません。
// memory動的配列 uint[] memory array8 = new uint[](5); bytes memory array9 = new bytes(9);サンプルコード(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L16-L18)では、状態変数としてもnewによる初期化が行われています。
// 可変長配列の初期化 uint[] array8 = new uint[](5); bytes array9 = new bytes(9);2.2 配列リテラル(Array Literals)と型推論
配列リテラルは、1つまたは複数の式の形をした配列で、すぐに変数へ代入されるものではありません。例えば[uint(1), 2, 3]のように記述します。
各要素の型は、最初の要素と周囲の文脈から推論されます。値に型が指定されていない場合、デフォルトで最小の型が使用されます:
[1, 2, 3]→ すべてuint8型(Solidity のデフォルト最小型)[uint(1), 2, 3]→ 最初の要素がuintと指定されているため、すべてuint型
次の例では、g()関数に渡す配列をuintに変換していないとエラーになります。配列リテラルの型は最初の要素で決まるため、関数の引数型(uint[3])と一致させる必要があるからです。
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract C { function f() public pure { g([uint(1), 2, 3]); // uintに変換しないと型が合わずエラー } function g(uint[3] memory _data) public pure { // ... } }この配列リテラルの使い方は、サンプルコードのarrayPush()(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L28-L33)にも登場します。uint[2] memory a = [uint(1), 2];のように、最初の要素をuintにキャストしてからmemory配列へ代入しています。
function arrayPush() public returns(uint[] memory){ uint[2] memory a = [uint(1), 2]; array4 = a; array4.push(3); return array4; }2.3 動的配列は要素ごとに代入する
動的配列を作成するときは、要素ごとに代入を行う必要があります。
uint[] memory x = new uint[](3); x[0] = 1; x[1] = 3; x[2] = 4;このパターンは、サンプルコードのinitArray()関数(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L20-L26)で実際に確認できます。external pure関数として宣言され、作成したmemory配列をそのまま返します。
function initArray() external pure returns(uint[] memory){ uint[] memory x = new uint[](3); x[0] = 1; x[1] = 3; x[2] = 4; return(x); }3. 配列のメンバー:length/push/pop
配列には以下のメンバーが用意されています:
| メンバー | 説明 | 適用対象 |
|---|---|---|
length | 配列の要素数を保持する。memory配列の長さは作成後に固定される | すべての配列 |
push() | 配列の最後に0要素を追加し、その要素の参照を返す | 動的配列のみ |
push(x) | 配列の最後に要素xを追加する | 動的配列のみ |
pop() | 配列の最後の要素を削除する | 動的配列のみ |
push()とpush(x)は、配列の末尾に要素を追加することで配列の長さを動的に伸ばします。push()は引数なしで末尾に0を追加し、追加された要素への参照を返します。pop()は末尾の要素を削除し、配列の長さを1つ縮めます。lengthは要素数を返しますが、memory配列の場合は作成時に固定され、push/popで変更することはできません。
上記のarrayPush()の例では、[1, 2]を代入したarray4に対してarray4.push(3)を実行することで、配列が[1, 2, 3]になることを確認できます。
4. 構造体(Struct)
Solidity では、structというフォーマットによって新しい型を定義できます。構造体の要素はプリミティブ型(基本型)でも参照型でも構いません。また、構造体は配列やマッピング(mapping)の要素となることも可能です。
4.1 構造体の定義
// 構造体 struct Student{ uint256 id; uint256 score; } Student student; // student構造体の初期化サンプルコード(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L38-L43)では、uint256型のidとscoreを持つStudent構造体が定義され、状態変数studentがインスタンス化されています。
4.2 構造体に値を代入する4つの方法
構造体への値の代入方法は全部で4つあります。
方法1:関数内でstorage型の構造体参照を作成する
Student storage _student = student;のように状態変数への参照をローカル変数に代入し、その参照を通じてメンバーを変更します。参照(ポインタ)であるため、_studentへの変更はそのまま状態変数studentに反映されます。
function initStudent1() external{ Student storage _student = student; // studentへの参照を代入 _student.id = 11; _student.score = 100; }方法2:状態変数の構造体を直接参照する
状態変数studentに直接アクセスして、メンバーごとに代入します。最もシンプルな方法です。
function initStudent2() external{ student.id = 1; student.score = 80; }方法3:構造体のコンストラクター式による代入
Student(3, 90)のように、構造体の定義順に引数を渡すコンストラクター式で代入します。引数の順序は構造体のメンバー定義順と一致している必要があります。
function initStudent3() external { student = Student(3, 90); }方法4:キー・バリュー形式による代入
Student({id: 4, score: 60})のように、メンバー名と値を明示的に対応付ける形式です。順序に依存しないため、コードの可読性が高く、複雑な構造体ほど誤りを防ぎやすくなります。
function initStudent4() external { student = Student({id: 4, score: 60}); }4つの方法はいずれも Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol#L45-L66 に実装されており、Remix でデプロイ後に各関数(initStudent1〜initStudent4)を呼び出して状態変数studentの変化を確認できます。このうち方法1と方法2はメンバーごとの代入、方法3と方法4は構造体全体の一括代入である点に注意してください。
5. まとめ
この講義では、Solidity におけるarrayとstructの基本的な使い方を紹介しました:
- 配列:
T[k](固定長)とT[](可変長)の2種類。bytesはbyte[]の代わりに使える省ガスな特殊な動的配列。 - 配列の作成:
memory動的配列はnew演算子で作成し、長さは固定。配列リテラルの型は最初の要素で決まる。 - 配列のメンバー:
length(要素数)、push()/push(x)(末尾への追加)、pop()(末尾の削除)。 - 構造体:
structで新しい型を定義でき、値の代入にはstorage参照・直接参照・コンストラクター式・キー・バリュー形式の4つの方法がある。
構造体は配列やマッピングの要素としても利用できるため、複雑なデータモデルを表現する際の基礎となります。次の講義では、Solidity のハッシュテーブルであるマッピング(mapping)を紹介します(第7講:マッピング)。なお、本講義の完全なサンプルコードは日本語版(Languages/ja/06_ArrayAndStruct_ja/ArrayAndStruct.sol)と中国語版(06_ArrayAndStruct/ArrayAndStruct.sol)の両方で公開されており、Remix に貼り付けてそのまま実行・検証できます。
【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程,供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考