变量数据存储和作用域
NOxONE 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值