变量数据存储和作用域

6/3/2024 solidity

# 1. 引用类型

在solidity中,引用类型主要有:数组(array)结构体(struct)映射(mapping),在声明时必须指定数据存储的位置,赋值时实际上传递的是地址(类似指针)

# 2. 数据位置

# 2.1 storage

存储在链上,类似硬盘,消耗gas多,合约状态变量默认为storage

# 2.2 memory

临时存储在内存,不上链,常用在函数参数和临时变量

# 2.3 calldata

临时存储在内存中,不上链,不可修改(immutable),常用于函数参数

function fCalldata(uint[] calldata _x) public pure returns(uint[] calldata) {
  // 参数为calldata数组,不能被修改
  // _x[0] = 0 // 修改会报错
  return(_x);
}

# 3. 数据位置和赋值规则

storage赋值给storage:创建引用,修改新变量会影响原变量

uint[] x = [1,2,3];

function fStorage() public {
  uint[] storage xStorage = x;
  xStorage[0] = 100; // 修改xStorage会影响x
}

storage赋值给memory:创建独立副本,修改新变量不会影响原变量

uint[] x = [1,2,3];

function fMemory() public view {
    uint[] memory xMemory = x;
    xMemory[0] = 100; // 修改xMemory不会影响x
}

memory赋值给memory:创建引用,修改新变量会影响原变量

其他情况赋值给storage:创建独立副本

# 4. 变量的作用域

# 4.1 状态变量

声明在合约内、函数外,存储在链上

contract Variables {
    uint public x = 1;
    uint public y;
    string public z;

    function foo() external {
        x = 5;
        y = 2;
        z = "0xAA";
    }
}

# 4.2 局部变量

声明在函数内,存储在内存中

function bar() external pure returns(uint) {
    uint xx = 1;
    uint yy = 3;
    uint zz = xx + yy;
    return(zz);
}

# 4.3 全局变量

预留关键字,不需声明

function global() external view returns(address, uint, bytes memory) {
    address sender = msg.sender;
    uint blockNum = block.number;
    bytes memory data = msg.data;
    return(sender, blockNum, data);
}

常用全局变量

  • blockhash : 给定区块的哈希值
  • block.coinbase: 当前区块矿工地址
  • block.gaslimit: 当前区块的gaslimit
  • block.number: 当前区块的number
  • block.timestamp: 当前区块的时间戳
  • gasleft() : 剩余 gas
  • msg.data: 完整call data
  • msg.sender: 消息发送者
  • msg.sig: calldata的前四个字节 (function identifier)
  • msg.value: 当前交易发送的wei值
    要么重构,
    要么享受!
    红莲华
    x
    loading...