Solidity中使用字面量初始化字符串数组为何如此复杂?
Solidity 内存字符串数组使用问题解答
你写的第一段代码无法正常编译,核心原因是Solidity对memory位置的动态数组有严格的初始化规则,不支持直接用["a", "b"]这类无类型标注的字面量数组做隐式赋值——这类字面量默认会被推导为定长内存数组,类型和动态长度的string[] memory不匹配。
1. 为什么长度声明为1的数组可以给索引1赋值?
这是Solidity编译器的静态检查漏洞,属于非法写法,没有任何语法合理性。new string[](1)只会在内存中分配1个元素的连续空间,合法索引只有0。给索引1赋值时,旧版本编译器不会做编译期的越界校验,但实际运行时这行操作会直接覆盖数组边界外的内存数据:轻则篡改同作用域下其他变量的取值,重则直接触发内存错误导致交易回滚,0.8.0之后的高版本编译器已经补上了这个检查,这类越界赋值会直接编译失败,生产环境绝对不能这么写。
2. 为什么字符串数组无法调用push()方法?
push()是仅storage位置动态数组支持的内置方法,和数组元素是不是字符串没有关系:
- 所有memory位置的数组,无论元素是什么类型,长度在初始化完成后就是固定值,不支持动态扩容/缩容,自然也没有
push()、pop()这类调整长度的方法。 - 如果是声明在合约存储位的
string[]动态数组,不管是全局状态变量还是函数里标记为storage的引用,都可以正常调用push()。
3. memory字符串数组分配字符串字面量的正确写法
这部分规则没有集中在文档的单一章节,零散分布在类型推导、内存数组的说明里,合法写法一共两种:
- 写法1:先初始化指定长度的数组,再逐个给索引赋值,这是兼容性最好的通用写法
// 初始化长度为2的内存字符串数组 string[] memory testArray = new string[](2); testArray[0] = "a"; testArray[1] = "b";
- 写法2:字面量初始化时显式指定元素类型,绕过定长数组的类型不匹配问题
// 第一个元素显式转为string类型后,整个字面量数组会被统一推导为string类型的定长数组 // 可直接赋值给同长度的动态string数组变量 string[] memory testArray = [string("a"), "b"];
注意:第二种写法要求字面量的元素数量和你需要的数组长度完全一致,毕竟memory数组初始化后长度无法修改。
内容的提问来源于stack exchange,提问作者AndCode
相关产品推荐
相关产品推荐

