Solidity 数组

数组是一种数据结构,它是存储同类元素的有序集合。

数组中的特定元素由索引访问,索引值从 0 开始。例如,声明一个数组变量,如 numbers,可以使用 numbers[0]、numbers[1] 表示单个变量。

数组大小可以是固定大小的,也可以是动态长度的。

对于 storage 数组,元素可以是任意类型(其他数组、映射或结构)。

对于 memory 数组,元素类型不能是映射类型,如果它是一个 public 函数的参数,那么元素类型必须是 ABI 类型。

类型为 bytes 和 string 的变量是特殊数组。bytes 类似于 byte[],但它在 calldata 中被紧密地打包。因此,相比于 byte[],bytes 应该优先使用,因为更便宜。

字符串 string 等价于 bytes,但不允许长度或索引访问。

1. 声明数组

固定长度数组

声明一个固定长度的数组,需要指定元素类型和数量,如下所示:

type arrayName [ arraySize ];

这是一维数组。arraySize 必须是一个大于零的整数数字,type 可以是任何数据类型。

例如,声明一个 uint 类型,长度为10的数组:balance,如下所示:

uint balance[10];

动态数组

声明一个动态数组,只需要指定元素类型,无需指定数量,如下所示:

type arrayName [];

这是一维数组。arraySize 必须是一个大于零的整数数字,type 可以是任何数据类型。

例如,声明一个 uint 类型的动态数组:balance,如下所示:

uint balance[];

2. 初始化数组

初始化数组,可以使用下面的语句:

uint balance[3] = [1, 2, 3]; // 初始化固定长度数组
uint balance[] = [1, 2, 3]; // 初始化动态数组
balance[2] = 5; // 设置第 3 个元素的值为 5

3. 访问数组元素

可以通过索引访问数组元素。例如

uint salary = balance[2];

上面的语句将从数组中取出第 3 个元素,并将值赋给 salary 变量。

4. 动态数组和固定长度数据的区别

固定长度的数组在运行期间,是无法改变长度的。而动态数组可以改变。

动态数组可以使用 push 方法,在末尾追加一个元素;使用 pop 方法,截掉末尾元素。

两种数组的常用操作方法示例如下:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SolidityTest {
   // 动态数组
   uint[] public arr=[1,2,3,4];
   // 固定长度数组
   uint[4] public arrFixed=[1,2,3,4];
   
   // 获得数组全部元素
   function getArr() external view returns(uint[] memory) {
      return arr;
   }

  // 固定长度数组操作
   function operatFixedArr() external {
      // 获得数组长度
      //uint len = arrFixed.length; // len = 4
      // 获得第二个元素
      //uint x = arrFixed[1]; // x = 2
      // 删除第二个元素,delete只将元素设置为初值,并不改变数组长度
      delete arrFixed[1]; // [1,0,3,4]
   }

   // 动态数组操作
   function operateDynamicArr() external {
      // 获得数组长度
      //uint len = arr.length; // len = 4
      // 追加一个元素
      arr.push(5); // [1,2,3,4,5]
      // 弹出一个元素
      arr.pop(); // [1,2,3,4]
      // 获得第二个元素
      //uint x = arr[1]; // x = 2
     // 删除第二个元素,delete只将元素设置为初值,并不改变数组长度
      delete arr[1]; // [1,0,3,4]
      // 删除第二个元素,并且长度减1
      removeAt(1); // [1,3,4]
   }

   // 删除数组元素,并且长度减1
   function removeAt(uint i) public {
      require(i>=0 && i<arr.length);
      for (uint k=i; k<arr.length-1;k++){
         arr[k] = arr[k+1];
      }
      arr.pop();
   }
}

5. 创建内存数组

我们可以使用 new 关键字在内存中创建动态数组。内存动态数组的长度一旦确定,不能改变。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SolidityTest{
   function getMemoryArr() external pure returns(uint[] memory) {
      uint[] memory arr = new uint[](3);
      arr[0] = 1;
      return arr;
   }
}

下一章:Solidity 结构体 struct

类似于C语言,solidity 也有结构体 struc 类型,用于表示复合型数据。结构体 struc 类型是引用类型。例如,一本书的信息:TitleAuthorBook IDOwner就可以用结构体来 ...