一. 关于变长数组。
string[],bytes[]
对于变长数组,在初始化分配空间前不可使用,可以通过new关键字来初始化一个数组。它们不能在使用new关键字初始化前使用下标方式访问。
storage
storage类型的动态数组有一个length属性,表示当前的数组长度。对于storage的变长数组,可以通过给length赋值调整数组长度。可以通过两种方式改变数组长度,index++及push方法。
contract test{ string[] strs = new string[](0); function test1() public returns(uint, string[]){ strs[strs.length++] = "a1"; return (strs.length, strs); } function test2() public returns(uint, string[]){ strs.push("b1"); return (strs.length, strs); } }
memory
而memory类型的动态数组,不支持修改length属性来调整数组大小。一旦new完,大小不可改变。
二. 存储位置storage和memory
memory赋值给storage
contract test1{ int i; struct S{string a;uint b;} function assign(S s) internal{ S tmp = s; // 报错,tmp是局部变量(storage类型),s是函数参数(memory类型) } function change(int changei) public returns(int){ i = changei; return i; // 返回等于changei的值 } }
storage转换为storage
contract test2{ struct S{string a;uint b;} //状态变量,合约内声明的公有变量,默认是storage的 S s; function convertStorage(S storage s) internal{ S tmp = s; // tmp也是storage类型的 tmp.a = "Test"; } function call() returns (string){ convertStorage(s); return s.a;//Test } }
memory赋值给storage
contract test3{ struct S{string a;uint b;} //默认是storage的 S s; function memoryToState(S memory tmp) internal{ s = tmp; //tmp是memory的,从内存中复制到状态变量中。 //修改旧memory中的值,并不会影响状态变量 tmp.a = "Test"; } function call() returns(string){ S memory tmp = S("memory", 0); memoryToState(tmp); return s.a; } }
memory赋值给局部变量(storage)
contract test4{ struct S{string a;uint b;} function memoryToLocal(S s) internal{ S tmp = s; // 报错,tmp是局部变量(storage类型),s是函数参数(memory类型) //修改变量为memory类型, 不会报错 S memory tmp = s; } }
storage赋值memory
contract test5{ struct S{string a;uint b;} S s = S("storage", 1); function storageToMemory(S storage x) internal{ S memory tmp = x;//由Storage拷贝到memory中 //memory的修改不影响storage tmp.a = "Test"; } function call() returns (string){ storageToMemory(s); return s.a; //storage } }
memory赋值memory
memory之间是引用传递,并不会拷贝数据。一个memory的引用类型赋值给另一个memory的引用,不会创建另一个新的拷贝。
contract test6{ struct S{string a;uint b;} //默认参数是memory function memoryToMemory(S s) internal{ S memory tmp = s; // tmp是memory,s是memory //引用传递 tmp.a = "other memory"; } function call() returns (string){ S memory mem = S("memory", 1); memoryToMemory(mem); return mem.a;//other memory } }
三. 字符串数组string[]
function getEntry(string[] fields, Entry entry) internal view returns (string[]) { //string[] values = new string[](fields.length); 报错,values是storage类型的,后面是memory for (uint i = 0; i < fields.length; i++) { values[i] = entry.getString(fields[i]); } return values; }
function getEntry(string[] fields, Entry entry) internal view returns (string[]) { string[] memory values = new string[](fields.length); // 正确 for (uint i = 0; i < fields.length; i++) { values[i] = entry.getString(fields[i]); } return values; }