实体阵列

这是Alex Pinto撰写的关于Solidity的第二个Aventus技术博客,这是我们区块链工程团队的最新成员。 您可以阅读他的第一篇有关在Solidity中使用字符串的文章

在很多情况下,我们希望将一组相似的数据传递给函数,但该数目可能会或可能不会受到限制。 在这种情况下,最基本的数据类型是数组(在某些情况下,可用于实现更高级的数据结构)。 如下所示,我们可以毫无问题地传递和返回数组。

实体阵列

上面使用uint数组,该数组表示256位整数,大小不受限制。 这意味着我可以将任何正确类型的数组传递给函数。 这也意味着我必须先在getArrayMultipliedByScalar初始化返回数组,然后才能使用它,因为在声明outArray_ ,它不会为其元素分配任何内存(它可以具有任何大小)。

为了比较; 如果我使用固定大小的数组,如下所示,则会发生两件事:

  • 我不再需要初始化传出数组。
  • 如果函数接收的数组大小不为3,则编译器将返回错误。
实体阵列

我们可以进行其他类型的数组,如booladdress -约多维数组但什么?

我们可以传递固定大小的二维数组:

实体阵列

可悲的是,使用动态数组会更加困难。

某些语言,例如BASIC和Pascal,通过索引元组索引二维数组。 在这些语言中,数组是真正的(矩形)矩阵。 但是在C派生的语言中,多维数组是数组的数组,而不是矩阵。 Solidity也是如此,需要花一些时间来理解此类型声明的含义: uint[2][4]应该读为(uint[2])[4] ,即4个数组每个尺寸为2。

当我们考虑动态数组时,这一点很重要。 我们可以同时拥有这两种:

实体阵列

上面的第一个示例是一个固定大小的数组,其中包含3个元素,每个元素都是一个动态数组。 在第二种情况下,我们有一个动态数组,但是它的元素是固定大小的数组。

我在下面讨论如何初始化fixedSizeArray ,这是两者中最有趣的情况。 关于dynamicArray ,因为它是一个动态数组,所以我们首先必须使用new为其分配内存,然后才能访问固定大小的元素。 下面的示例起作用:

实体阵列

多维动态数组的初始化

让我们更详细地研究一个类似于上面的示例:

实体阵列
TypeError:uint256 [3]类型的内存不能隐式转换为预期的uint256 [3]类型的存储指针。

数组fixedSizeArraydynamicArray声明为协定的状态变量,因此必须存储引用。 无法使用new表达式来初始化Storage阵列,因为它们是memory类型的。 尽管如此,我们可以使用内存数组表达式初始化fixedSizeArray内部的每个数组,如上所示。

为了进行比较,我还列举了两种情况,其中我尝试将一个内存阵列分配给一个显式存储。 在构造函数中,这有效,但在第二个函数中无效。 为什么?

这是因为storageArraylocalStorageArray的类型不完全相同。 前者是合同的状态变量,当在构造函数中被引用时,其类型为uint256[3] storage ref (要看到这一点,请将赋值的正确值更改为非法值,例如7,并显示错误消息将向您显示所涉及的类型)。 相比之下, localStorageArray的类型为uint256[3] storage pointer 细微的差别。 在第一种情况下,我们引用了存储中的位置,并且分配将存储器阵列复制到该存储中。 在第二种情况下,我们尝试分配给局部变量,该局部变量根据文档仅创建对先前指针的新引用:

不过,对本地存储变量的分配仅分配了一个引用,即使此状态在此期间被更改,该引用也始终指向状态变量。
实体阵列
摘自Solidity文档

在上面的示例中, y是指向x的相同位置的指针,修改其中一个会导致另一个发生变化。 但是在我们的例子中,我们试图将一个内存数组分配给一个存储变量,该变量的类型不同,无法产生指向该内存位置的指针。

另一方面,当我们初始化fixedSizeArray ,实际上是指存储引用。 在这种情况下,我们可以从一个内存阵列进行分配,这具有在目标上完全复制源的作用,从而擦除了其所有先前的内容。

我们可以将多维数组传递给函数吗?

这取决于!

实体阵列

我们可以使用Solidity的多态性来编写四个具有相同名称和不同签名的函数,从而探索动态和固定大小的二维数组的所有组合。

这些函数中的两个是非法的,只是因为它们的特定数组类型无法传递给函数。 非法是一个很强的词:错误表明可以使用该类型,但只能用于新的实验性ABI编码器; 为了使用它,有必要包含pragma experimental ABIEncoderV2; 但是,我们将收到一条警告,指出不应在生产代码中使用它。

随着新版本的Solidity的出现,将来可能会取消此限制,但是目前,我只是不使用这些功能,而是寻求解决方法。

这两种类型之间的共同特征是数组的内部类型 (即其元素的类型)是动态的,大小未知。 这些类型不能传递给函数,也不能从函数返回。

我将用另一个示例来结束这篇文章:

实体阵列

最后两个功能是非法的。 之所以与之前所说的一切非常一致,是因为stringbytes是动态类型。 具体来说,它们是数组:分别为UTF-8字符和字节的数组 因此,上述返回类型不是像getIntsgetAddresses那样的真正简单的一维数组,而是具有动态内部类型的二维数组。 因此,在Solidity的当前阶段不能将它们传递到函数中或从函数中返回。

关于作者

实体阵列

Alex是Aventus的软件工程师,在区块链工程团队中工作。 他在技术领域拥有20年的经验,并获得了计算机科学博士学位和密码学博士学位。 作为研究的一部分,Alex 发表了有关Kolmogorov复杂性,密码学,数据库匿名化和代码混淆的论文。

Alex还曾在Maia大学学院任教七年,包括指导理学学士学位计算机科学和信息系统与软件的学位课程。

From: https://hackernoon.com/arrays-in-solidity-b65c1326f48b