-
有一下三种类型:
- storage: 表示变量存储在链上。(合约里的状态变量默认都是
storage
) - memory: 表示变量储存在内存上。(函数里的参数和临时变量一般用
memory
) - calldata: 表示变量储存在内存上且不能修改(用于外部函数的只读输入参数,效率高于memory)
注:相同类型变量赋值,栈变量名改变,指针堆是相同的。所以改变新变量,原变量同步改变
- storage: 表示变量存储在链上。(合约里的状态变量默认都是
- 状态变量:存储在链上,所有合约内函数都可以访问。(
gas
消耗最高) - 局部变量:存储在内存,仅在函数执行有效。(
gas
消耗低) - 全局变量:无需申明,属于
solidity
关键字。三个常用:msg.sender
,block.number
和msg.data
。完整全局变量内容看此文档 - 全局变量-以太坊和时间单位:
- 以太坊单位: 1 wei = 1 ; 1 gwei = 1e9 = 1000000000; 1 ether = 1e18 = 1000000000000000000
- 时间单位: 1 seconds = 1 ; 1 minutes = 60; 1 hours = 3600; 1 days = 86400
引用类型: 数组(array
)和结构体(struct
)。使用时必须声明存储位置
-
固定长度数组
uint[8] array1; bytes1[5] array2; address[100] array3;
-
可变长度数组(动态数组)
uint[] array4; bytes1[] array5; address[] array6; bytes array7;
注意:bytes
比较特殊,是数组,但是不用加
[]。另外,不能用byte[]
声明单字节数组,可以使用bytes
或bytes1[]
。bytes
比bytes1[]
省gas。
- 对于memory动态数组使用new,必须声明长度,且声明后长度不能改变
- 对于数组字面常数,默认最小单位类型是
uint8
,所以需要定义为uint256。例:[1,2,3]
要写成[uint(1),2,3]
-
length
: 数组有一个包含元素数量的length
成员,memory
数组的长度在创建后是固定的。 -
push()
:动态数组
拥有push()
成员,可以在数组最后添加一个0
元素,并返回该元素的引用。 -
push(x)
:动态数组
拥有push(x)
成员,可以在数组最后添加一个x
元素。 -
pop()
:动态数组
拥有pop()
成员,可以移除数组最后一个元素。注意:
- 数组越界:访问不存在的索引会导致运行时错误,所以在访问数组元素时要确保索引在合法范围内。
- Gas 消耗:动态数组的操作(尤其是
push
和pop
)涉及写入存储,因此会消耗较多的 Gas 费。在处理大数组时要小心 Gas 的消耗。
-
Example:
struct Student{ uint256 id; uint256 score; } Student student;
-
结构体赋值的四种方法:
// 四种方法结构体赋值 function change1() external { Person storage _person = person; _person.name = "a"; _person.age = 22; } function change2() external { person.name = "b"; person.age = 23; } function change3() external { person = Person("c", 24); } function change4() external { person = Person({ name:"d", age: 25 }); }