Solidity 从入门到实战(六)
注意:本专栏主要来自于https://www.bilibili.com/video/BV1St411a7Pk?p=11&spm_id_from=pageDriver的学习笔记以及https://blog.csdn.net/weixin_45067603/article/details/105751748
memory(内存存储)与storage(区块链存储)
具体的区别可访问:『0007』- Solidity状态变量、局部变量与memory 、storage之间的爱恨情仇
pragma solidity ^0.4.0;contract memoryTest{
uint[] arrx; //这个状态变量存储在区块链的网络之上//当我们调用此函数的时候,会创建一个可变数组,会在内存中为它分配空间function test(uint[] arry) returns(uint){
arrx =arry;//将内存的arry拷贝给区块链的arrx变量//当我们在函数内部定义了一个可变长度的数组时,实际上,它默认的类型是storage类型,它指向了区块链的arrx,所以当我修改z的元素的时候,我实际上在操作区块链上的arrxuint []storage z =arrx;//通过指针实际上修改了区块链上arrx的长度,说明z和arrx是一样的,操作z的时候,会改变arrx的值z[0] =100;z.length =100;}//返回arrx第一个元素function test2() returns(uint){
return arrx[0];}//返回arrx的长度function test3() returns(uint){
return arrx.length;}
}
结构体
案例1
简单使用结构体
pragma solidity ^0.4.0;contract structTest{
//定义结构体 struct student{
uint grade;string name;}struct student2{
uint grade;string name;//student stu; 结构体内部不能包含自己本身,但是可以是动态长度的数组,也可以是映射student2[] stu; mapping(uint =>student2) test;}//结构体初始化function init()view returns(uint,string){
student memory s = student(100,"吴彦祖");return(s.grade,s.name);}//结构体初始化第二种方式function init2()view returns(uint,string){
student memory s = student({
grade:100,name:"吴彦祖"});return(s.grade,s.name);}
}
案例2
结构体中的mapping特性
pragma solidity ^0.4.0;contract structTest{
struct student{
uint grade;string name;mapping(uint =>string) map;}student wyz;//默认为storage类型,只能够用storage类型来操作结构体中的mapping类型//memory的对象不能够直接操作struct结构体中的mappingfunction init() view returns(uint,string,string){
//在初始化结构体的时候,忽略掉mapping类型student memory s = student(100,"吴彦祖");//将内存中的s对象赋值给wyz这样的storage对象wyz =s;//我们只能通过storage对象来操作mapping属性wyz.map[0] ="helloworld";return(s.grade,s.name,wyz.map[0]);}
}
案例3 (memory转storage)
总结
- storage可以接受memory的值
- memory的改动不影响storage
- storage的改动不影响memory
pragma solidity ^0.4.0;contract structTest{
struct student{
uint grade;string name;}student stu;//函数的形参传递了指针引用//要是函数以结构体作为参数,那么函数修饰符必须有private/internalfunction test(student memory s)internal{
//将s的值赋给了区块链上的stustu =s;//修改函数形参s,只是修改内存中的空间,没有修改掉区块链上的空间,因为它们两个是完全独立的空间s.name="吴彦祖";}function test2(student memory s1)internal{
stu =s1;//修改区块链中的值stu.name ="胡歌";}function call() returns(string){
//tmp在内存中开辟空间,指向studentstudent memory tmp = student(100,"tmp");test(tmp);return stu.name;}function call2() returns(string){
student memory tmp = student(100,"tmp");test2(tmp);return tmp.name; //但是该值没有发生变化}
}
内存地址图
案例4(storage转memory)
总结
- storage可以接受memory的值
- memory的改动不影响storage
- storage的改动不影响memory
pragma solidity ^0.4.0;contract structTest{
struct student{
uint grade;string name;}//定义结构体,并初始化student stu=student(100,"赵丽颖");//storage类型作为函数的参数function test(student storage s)internal view returns(string){
student memory lina = s;lina.name="吴彦祖"; //改变内存中姓名,观察区块链中的姓名是否改变return s.name;}function test2(student storage s1)internal view returns(string){
student memory liming =s1;s1.name ="胡歌"; //改变区块链中的姓名,观察内存中的姓名是否改变return liming.name;}function call() view returns(string) {
return test(stu); //没改变}function call2() view returns(string){
return test2(stu); //没改变}
}
案例5(memory转memory)
pragma solidity ^0.4.0;contract structTest{
struct student{
uint grade;string name;}student stu=student(100,"赵丽颖");//memory类型之间的转换,由于solidity的优化,是通过指针来传递的function test(student memory s)internal view returns(string){
student memory lina = s;lina.name="吴彦祖";//都是在内存中,由于lina指向s,修改lina的name属性,相当于修改s的name属性return s.name; }function test2(student memory s1)internal view returns(string){
student memory liming =s1;s1.name ="胡歌";//都是在内存中,由于liming指向s1,修改liming的name属性,相当于修改s1的name属性return liming.name;}function call() view returns(string) {
return test(stu);//吴彦祖}function call2() view returns(string){
return test2(stu);//胡歌}
}
案例6(storage转storage)
pragma solidity ^0.4.0;contract structTest{
struct student{
uint grade;string name;}student stu=student(100,"赵丽颖");function test(student storage s)internal view returns(string){
student storage lina = s;lina.name="吴彦祖";return s.name;}function test2(student storage s1)internal view returns(string){
student storage liming =s1;s1.name ="胡歌";return liming.name;}function call() view returns(string) {
return test(stu);}function call2() view returns(string){
return test2(stu);}
}
枚举
格式:enum 变量名{x,y,z} 没有分号
pragma solidity ^0.4.0;contract enumTest{
enum men{
xiaoming,xiaowang,xiaozhang}men studyMen = men.xiaoming;function getEnum()public pure returns(men){
return men.xiaozhang;}function oneDayStudy()public payable returns(string){
//按照视频中所写的,会出现错误,用此种方式不出错require(studyMen == men.xiaoming);studyMen = men.xiaowang;return "oneDayStudy with xiaoming";}function twoDayStudy()public view returns(string){
require(studyMen == men.xiaowang);return ("twoDayStudy with xiaowang");}
}