以太坊solidity学习记录(一)新版在线remix编译器的使用(2020.4.27)
以太坊solidity学习记录(二)基础操作整理
以太坊solidity学习记录(三)基础数据操作
以太坊solidity学习记录(四)地址与交易
以太坊solidity学习记录(五)函数入门
以太坊solidity学习记录(六)内存与结构体
结论:
1.在solidity合约内部
函数外部声明的变量默认储存在storage里
函数内部声明的变量默认储存在memory里
storage | memory | |
---|---|---|
储存的变量 | 函数外部声明的变量,即状态变量 | 函数内部声明的变量,即局部变量 |
存储的位置 | 区块链上,永久存在 | 内存中,运行完之后销毁 |
运行的位置 | 区块链网络上 | 单个节点 |
传递属性 | 指针传递 | 值传递 |
可参考
Solidity的数据位置特性深入详解(九)| 入门系列(老是遇到转换问题的来看看)
『0007』- Solidity状态变量、局部变量与memory 、storage之间的爱恨情仇
直接看代码吧
pragma solidity ^0.4.0;
contract structtest1{
struct stu{
uint id;
string name;
mapping(uint=>string) maptest; //mapping即使在结构体内,初始化时也是可以忽略的
}
function init1() public returns(uint,string){
stu memory student1= stu(1234,'stu1');
return (student1.id,student1.name); //初始化方法一
}
function init2() public returns(uint,string){
stu memory student2=stu({name:'stu2',id:5678});
return (student2.id,student2.name); //初始化方法二
}
stu tempstudent1; //只要是函数外面的都是storage
function mappingtest() public returns(uint,string){
stu memory student3=stu({name:'stu3',id:5678});
//student3.maptest[100]='mapstu3';
//直接赋值会报错,因为storage不能转化为memory
tempstudent1=student3;
//此时tempstudent1,student3使用的是统一指针,所以下面对tempstudent1修改就等于修改student3
tempstudent1.maptest[100]='how to map';
return (student3.id,tempstudent1.maptest[100]);
}
}
运行结果
init1()
init2()
mappingtest()
结论
1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal
2.storage可以接受storage的值,并且storage的改动影响其它storage
代码
contract STS{ //此例temp,student1均为storage
struct stu{
uint id;
string name;
}
stu student1;
function structtest(stu storage temp) internal{ //传入storage结构体
student1=temp; //赋值
temp.id=2; //即使只是修改并未再次赋值,student1的id也会改变
}
function tets() public view returns(uint){
structtest(student1);
return (student1.id);
}
}
结论:
1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal
2.storage可以接受memory的值
3.memory的改动不影响storage
4.storage的改动不影响memory
代码
contract MTS{
struct stu{
uint id;
string name;
}
stu student1;
uint memorynum; //记录memory的值是否受storage影响
function structtest1(stu memory temp) internal{
student1=temp; //storage可以接受memory的值,但是memory的改动不影响storage
temp.id=2; //改变memory的值,看看storage值是否随之改变
memorynum=temp.id; //如果student1随着temp改变,那么说明storage受memory影响
}
function structtest2(stu memory temp) internal{
student1=temp;
student1.id=3;//改变storage的值,看看memory值是否随之改变
memorynum=temp.id; //如果temp随着student1改变,那么说明memory受storage影响
}
function test1() public returns(uint,uint){
stu memory temp=stu(1,'a');
structtest1(temp);
return (student1.id,memorynum);
}
function test2() public returns(uint,uint){
stu memory temp=stu(1,'a');
structtest2(temp);
return (student1.id,memorynum);
}
}
结论:
1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal
2.storage可以接受memory的值
3.memory的改动不影响storage
4.storage的改动不影响memory
代码
contract STM{
struct stu{
uint id;
string name;
}
stu student1=stu(1,'a');
uint memorynum; //记录memory的值是否受storage影响
function structtest1(stu storage temp) internal{
stu memory student2=temp;
student2.id=2;//改变memory的值,看看storage值是否随之改变
memorynum=student2.id;
}
function structtest2(stu storage temp) internal{
stu memory student2=temp;
temp.id=3;//改变storage的值,看看memory值是否随之改变
memorynum=student2.id;
}
function test1() public view returns(uint,uint){
structtest1(student1);
return (student1.id,memorynum);
}
function test2() public view returns(uint,uint){
structtest2(student1);
return (student1.id,memorynum);
}
}
结论
1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal
2.在此处中看似不影响,但是solidity自我优化是的传入的memory转化为指针,然后连锁导致后面的也全部变为指针,相当于storage转storage了
代码
contract MTM{
struct stu{
uint id;
string name;
}
function structtest(stu memory temp) internal{
stu memory student2;
student2=temp;
student2.id=2;
}
function tets() public view returns(uint){
stu memory student1=stu(1,'a');
structtest(student1);
return (student1.id);
}
}
结论:
1.enum不能为空,不能存在中文
2.作用:提高可读性
代码:
contract enumtest{
enum enuma{ac,bc,cc,dc} //不需要分号
function testenumvalue() public view returns(enuma,enuma,enuma,enuma){//虽然return的是数字,但是并不能写uint
return (enuma.ac,enuma.bc,enuma.cc,enuma.dc);//必须前面加名字.
}
}