storage(指针传递)

pragma solidity ^0.4.4;

contract Person {

    string public  _name;

    function Person() {
        _name = "lisi";
    }

    function f() {

        modifyName(_name);
    }

    function modifyName(string storage name) internal {

        var name1 = name;
    }
}

如果想要在modifyName函数中通过传递过来_name来修改它的值,那么必须将方法参数的类型显示设置为storage类型,storage类型拷贝的不是值,而是参数指针,当调用modifyName(_name)时,相当于把_name,name,name1三个指针同时指向同一个对象,可以近似认为修改三个中任一个都可修改对应的值。

注意:

当方法参数为storage类型时,方法的类型必须为internal或者private。

状态变量的空间排布

静态变量(除mapping和动态数组类型之外的)都从位置0开始在storage中连续排布。尽可能的要少于32个字节的各个项目被打包到一个存储槽(slot)中。

  • 存储槽中的第一项是被低位对齐的。
  • 基本类型只使用存储它们所需的那么多字节。
  • 如果基本类型不适合存储插槽的其余部分,则将其移动到下一个存储插槽。
  • 结构和数组数据总是会启动一个新的槽并占据整个槽(结构或数组内的项会根据他们的索引紧密排列)。

根据上述规则,在未填充情况下,mapping或动态数组本身占据某个位置p的存储空间。 对于动态数组,一个存储槽就存储了数组中所有元素,数组数据位于keccak256(p)。 对于长度为零的mapping,该槽未被使用但已被占用,mapping key的值位于keccak256(k+p),如果该key对应的value是非基本类型,则通过添加keccak256(k+p)的偏移量来查找位置。

bytes 和 string 都存储在同一插槽,如果他们是短类型那么也同时存储长度。注意:如果该数据已经有31字节长度,它存储在高位字节中(左对齐),低位字节存储length * 2,如果更长空间不够的话,主插槽存储length * 2 + 1,数据value 存储在keccak256(slot)。

pragma solidity ^0.4.0;

contract C {
  struct s { uint a; uint b; }
  uint x;
  mapping(uint => mapping(uint => s)) data;
}

比如:data[4][9].b 该项数据位于 keccak256(uint256(9) + keccak256(uint256(4) + uint256(1))) + 1

注意:

在for (var i = 0; i < arrayName.length; i++) { ... }, i的类型是uint8,因为这是存放值0最小的类型。如果数组元素超过255个循环将不会终止。因为2的8次方是256。

results matching ""

    No results matching ""