# Learn Solidity Series 4: arrays

By [Renaissance Labs](https://paragraph.com/@renaissance-labs) · 2022-02-25

---

![Learn Solidity Series](https://storage.googleapis.com/papyrus_images/c5b855393055dde7486bb9f6dae8f17adcb798ba1d0184de400c6948143bb6d9.png)

Learn Solidity Series

> Solidity中，有两种类型的数组：存储数组和内存数组。

存储数组(Storage Arrays)
--------------------

> 这些数组被声明为状态变量，并且可以具有固定长度或动态长度。动态存储数组可以调整数组的大小，它们通过访问`push()`和`pop()`方法来调节长度。

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

contract A { uint256\[\] public numbers;// 动态长度数组 address\[10\] private users; // 固定长度数组 uint8 users\_count;

      function addUser(address _user) external {
          require(users_count < 10, "number of users is limited to 10");
          users[users_count] = _user;
          users_count++;
      }
      
      function addNumber(uint256 _number) external {
          numbers.push(_number);
      }
    

内存数组(Memory Arrays)
-------------------

> 这些数组以`memory`作为其数据位置声明。它们也可以具有固定长度或动态长度，但是不能调整动态大小的内存数组的大小(即，不能调用`push()`和`pop()`方法)，数组的大小必须预先计算。也可以使用`new`关键字声明动态大小的内存数组。

Type\[\] memory a = new Type

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

contract B {

     function createMemArrays() external view {
         uint256[20] memory numbers;
         numbers[0] = 1;
         numbers[1] = 2;
         
         uint256 users_num = numbers.length;
         address[users_num] memory users1; // 错误 :  应该是整数常量或常量表达式
    
         address[] memory users2 = new addressUnsupported embed;
         users2[0] = msg.sender; // OK
         users2.push(msg.sender); // 错误 : member push is not available
         
     }
    }
    

注意，numbers\[0\] = 1; 因为根据内存中布局的描述，`array`将指向零插槽，因此切勿写入。请记住，在使用数组之前，请务必先对其进行初始化，以便获取有效的地址。

### 数组切片(Array Slices)

> 数组切片只能与`calldata`数组一起使用，形式为`x[start:end]`。切片的第一个元素是`x [start]`，最后一个元素是`x[end-1]`。开始和结束都是可选的：开始默认为0，结束默认为数组的长度。

byte\[\]和bytes
--------------

> 这些数组可以保存任意长度的原始字节数据。

区别在于，byte \[\]遵循数组类型的规则，并且如文档 Solidity中的内存数组的描述，数组的元素总是占据32个字节的倍数。这意味着如果一个元素的长度小于32字节的倍数，则将对其进行填充，直到其适合所需的大小为止。对于byte数组，每个元素将浪费31个字节。值得说明的是，从内存中读取或写入一个字(32个字节)会消耗 3 gas，这就是为什么建议使用bytes而不是byte\[\]的原因。

而bytes或string不是这种情况。string字符串是UTF-8数据的动态数组。与其他语言相反，Solidity中的string不提供获取字符串长度或执行两个字符串的连接或比较的功能(需要使用库)。 可以使用bytes()将字符串转换为字节数组。这将返回字符串的UTF-8表示形式的低级字节。 _注意：可以将一个字符编码为一个以上的字节，因此字节数组的长度不一定是字符串的长度。_ string与bytes 文档的大多数使用`bytes32`而不是`string`，并且如果可以限制字符串的字节数，则应该使用值类型`bytes1` ... `bytes32`，因为便宜得多。

---

*Originally published on [Renaissance Labs](https://paragraph.com/@renaissance-labs/learn-solidity-series-4-arrays)*
