solidity中的引用类型
solidity中的引用类型包括数组array,结构体struct和映射mapping。这类变量占空间大,赋值时候直接传递地址(类似指针)。由于这类变量比较复杂,占用存储空间大,我们在使用时必须要声明数据存储的位置。
solidity数据存储位置有三类:storage,memory和calldata。不同存储位置的gas成本不同。storage类型的数据存在链上,类似计算机的硬盘,消耗gas多;memory和calldata类型的临时存在内存里,消耗gas少。大致用法:
-
storage
:合约里的状态变量默认都是storage
,存储在链上。 -
memory
:函数里的参数和临时变量一般用memory
,存储在内存中,不上链。 -
calldata
:和memory
类似,存储在内存中,不上链。与memory
的不同点在于calldata
变量不能修改(immutable
),一般用于函数的参数。例子:
function fCalldata(uint[] calldata _x) public pure returns(uint[] calldata){
//参数为calldata数组,不能被修改
// _x[0] = 0 //这样修改会报错
return(_x);
}
数据位置和赋值规则
1.storage:赋值给函数中的storage时候,会创建引用,改变新变量会影响原变量。
uint[] x = [1,2,3]; // 状态变量:数组 x
function fStorage() public{
//声明一个storage的变量 xStorage,指向x。修改xStorage也会影响x
uint[] storage xStorage = x;
xStorage[0] = 520;
}
2.storage赋值,会创建独立的复本,修改其中一个不会影响另一个。
uint[] x = [1,2,3]; // 状态变量:数组 x
function fMemory() public view{
//声明一个Memory的变量xMemory,复制x。修改xMemory不会影响x
uint[] memory xMemory = x;
xMemory[0] = 100;
xMemory[1] = 200;
uint[] memory xMemory2 = x;
xMemory2[0] = 300;
}
试试在remix上运行一下吧,代码如下
pragma solidity ^0.8.4;
contract DataStorage{
uint[] x = [1,2,3];
function fStorage() public{
uint[] storage xStorage = x;//声明storage变量xStorage,指向x
xStorage[0] =520;
}
function fmemory() public view{
uint[] memory xMemory = x;//声明memory变量xMemory,指向x
xMemory[0] = 520;
}
function fcalldata(uint[] calldata _x) public pure returns(uint[] calldata){
return(_x);//calldata数组不能被修改,_x[0]=0;
}
}
变量作用域
solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)。
1.状态变量
状态变量是数据存储在链上的变量,所有合约内函数都可以访问 ,gas消耗高。状态变量在合约内、函数外声明:
contract Variables {
uint public x = 1;
uint public y;
string public z;
}
函数中也可改变状态变量的值
function fChange() external{
x = 5;
y = 2;
z = "solidity";
}
2.局部变量
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存储在内存里,不上链,gas低。局部变量在函数内声明:
function fChange() external pure returns(uint){
uint x = 1;
uint y = 3;
uint z = x + y;
return(z);
}
3.全局变量
全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:
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);
}
在上面例子里,我们使用了3个常用的全局变量:
msg.sender:请求发起地址
block.number:当前区块高度
msg.data:请求数据文章来源:https://www.toymoban.com/news/detail-734457.html
下面我将还列举出一些常用的全局变量文章来源地址https://www.toymoban.com/news/detail-734457.html
-
blockhash(uint blockNumber)
: (bytes32
)给定区块的哈希值 – 只适用于256最近区块, 不包含当前区块。 -
block.coinbase
: (address payable
) 当前区块矿工的地址 -
block.gaslimit
: (uint
) 当前区块的gaslimit -
block.number
: (uint
) 当前区块的number -
block.timestamp
: (uint
) 当前区块的时间戳,为unix纪元以来的秒 -
gasleft()
: (uint256
) 剩余 gas -
msg.data
: (bytes calldata
) 完整call data -
msg.sender
: (address payable
) 消息发送者 (当前 caller) -
msg.sig
: (bytes4
) calldata的前四个字节 (function identifier) -
msg.value
: (uint
) 当前交易发送的wei
值
到了这里,关于solidity第五课——变量数据存储和作用域的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!