Solidity 从入门到实战(六)
注意:本专栏主要来自于https://www.bilibili.com/video/BV1St411a7Pk?p=11&spm_id_from=pageDriver的学习笔记以及https://blog.csdn.net/weixin_45067603/article/details/105751748
memory(内存存储)与storage(区块链存储)
pragma solidity ^0.4.0;
contract memoryTest{
uint[] arrx; //这个状态变量存储在区块链的网络之上
//当我们调用此函数的时候,会创建一个可变数组,会在内存中为它分配空间
function test(uint[] arry) returns(uint){
arrx =arry;//将内存的arry拷贝给区块链的arrx变量
//当我们在函数内部定义了一个可变长度的数组时,实际上,它默认的类型是storage类型,它指向了区块链的arrx,所以当我修改z的元素的时候,我实际上在操作区块链上的arrx
uint []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结构体中的mapping
function 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/internal
function test(student memory s)internal{
//将s的值赋给了区块链上的stu
stu =s;
//修改函数形参s,只是修改内存中的空间,没有修改掉区块链上的空间,因为它们两个是完全独立的空间
s.name="吴彦祖";
}
function test2(student memory s1)internal{
stu =s1;
//修改区块链中的值
stu.name ="胡歌";
}
function call() returns(string){
//tmp在内存中开辟空间,指向student
student 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");
}
}