对于复杂类型例如array,struct都有一个都有一个额外的注解(annotation),多是storage,memory,calldata之一。根据上下文老是有一个默认的注解类型。可是通常能够经过storage和memory关键字显示的修改。数组
对于函数的出参和入参通常默认的是memory类型(external 函数的入参例外是强制的calldata类型)函数
对于局部变量默认的是storage类型(能够经过memory修改)区块链
对于状态变量强制的是storage类型(不能经过memory修改)ui
会写入区块链中指针
不会持久化(不会写入到区块链中)code
不可修改,不可持久化orm
pragma solidity ^0.4.18; contract DL{ uint [] stateVariable;//状态变量(state variable) function normal(uint [] inArg) public returns(uint outArg){ uint [] localVar;//局部变量(本地变量,local variable) return 0; } function cd(uint [] inArg) external returns(uint outArg){ return 0; } }
上面代码的stateVariable就是状态变量,inArg就是入参,outArg就是出参string
stateVariable的data location就是storageit
localVar是局部变量,data location是memoryio
函数normal的inArg的data location是memory outArg也是memory
函数cd的inArg的data location是calldata outArg是memory
function storaegPara(Person storage allen) public returns(uint8 age,string name){ person = allen; return (person.age,person.name); }
像上面这种就会出编译错误。
pragma solidity ^0.4.18; contract DL{ struct Person{ uint8 age; string name; } Person person = Person({age:20,name:"tim"});//状态变量,强制storage(state variable) function storaegPara(Person storage allen) internal returns(uint8 age,string name){ person = allen; return (person.age,person.name); } function testStoraegPara() returns(uint8 age,string name){ Person allen = Person({age:22,name:"allen"}); return storaegPara(allen); } }
像上面的就会编译错误。从前面咱们知道:
Person allen = Person({age:22,name:"allen"});
等价于:
Person memory allen = Person({age:22,name:"allen"});
当调用storaegPara(allen)的时候,至关于把一个memory的局部allen变量赋值给一个storage的局部变量allen。
这是由于storage是静态分配存储空间的,对于storage的赋值,更像是对指针的赋值。
pragma solidity ^0.4.18; contract DL{ struct Person{ uint8 age; string name; } Person person = Person({age:20,name:"tim"});//状态变量,强制storage(state variable) function storaegPara(Person memory allen) internal returns(uint8 age,string name){ person = allen; return (person.age,person.name); } function testStoraegPara() returns(uint8 age,string name){ Person memory allen = Person({age:22,name:"allen"}); return storaegPara(allen); } }
storage能够对memory进行赋值,执行的是拷贝操做。(修改新的memory变量不会影响原来storage变量)
memory对memory的赋值是引用
同类赋值(memory对memory,storage对storage)是引用,至关于指针不会执行数据拷贝。
memory和storage相互赋值,执行的是数据拷贝,可是注意memory不能对局部storage赋值
对于变长数组必须使用new初始化以后才能访问
new 产生的是memory类型的,不能转换为局部的storage,因此能够看到在函数中下面的代码是会出编译错误的:
uint [] storage data = new uint[](1);
对于storage的变长数组,能够经过给length赋值调整数组长度。还能够使用后面提到的push()方法,来隐式的调整数组长度
对于memory的变长数组,不支持修改length属性,来调整数组大小。memory的变长数组虽然能够经过参数灵活指定大小,但一旦建立,大小不可调整