Solidity中结构体初始化空数组后如何写入地址数据
解答
首先明确Solidity中数组操作的核心规则:
- 用
new关键字在memory位置创建的数组,长度在创建时就固定了,无论初始化传入的长度是多少,后续都不能调用push/pop修改长度,只能通过索引修改已存在位置的元素值。 - 只有
storage位置的动态数组,才支持动态追加、删除元素的操作。
你给出的示例代码的写法本身就是正确可行的,它的逻辑完全绕开了memory数组不能动态扩展的限制:
- 第一步在内存中创建
Room类型的临时结构体时,传入new address[](0)只是为了满足memory结构体初始化必须显式赋值所有字段的要求,这个长度为0的临时数组本身不需要做任何元素写入操作。 - 调用
rooms.push(room)时,EVM会把内存中临时的Room结构体完整拷贝到链上存储(storage)的rooms数组末尾,此时rooms[rooms.length - 1]是storage类型的结构体实例,它的players字段也随之变成storage类型的动态数组。 - 后续直接对这个storage下的
players数组调用push方法写入地址即可,也就是示例中rooms[rooms.length-1].players.push(msg.sender);这行代码的作用,完全可以正常运行。
补充注意点
- 不要尝试在memory阶段给初始长度为0的数组写入元素:长度为0的memory数组没有可访问的索引位,直接按索引赋值会触发越界错误,且memory数组本身不支持
push操作。 - 如果你确实需要在memory阶段先填充好数组内容再存入storage,初始化memory数组时就要直接指定最终需要的长度,再按索引赋值。比如初始化时就要存入当前调用者地址,可以这么写:
function createRoom() public { // 初始化时直接指定数组长度为1 address[] memory initPlayers = new address[](1); initPlayers[0] = msg.sender; Room memory room = Room(initPlayers, 0, 0); rooms.push(room); OnCreateRoom(msg.sender, 0); }
- 对于已经存入storage的
Room实例,后续要追加玩家地址时,只要拿到对应结构体的storage引用,直接调用players.push(目标地址)即可,不需要重新初始化数组。
以上规则在Solidity 0.4.x版本中生效,更高版本的语法细节有调整,但memory与storage位置的数组操作限制逻辑一致。
内容的提问来源于stack exchange,提问作者Hasnat Pie
相关产品推荐
相关产品推荐

