基于以太坊的智能合约开发Solidity(内存结构体篇)

参考教程:【内存、引用与持久化存储】1、内存与区块链——storage与memory原理_哔哩哔哩_bilibili

1、storage与memory:

pragma solidity ^0.5.17;contract MemoryTest
{
uint z = 1;   //这是在合约中定义的状态变量,它会永久地(随本合约)存储在区块链上,也就是storage中,直至合约被销毁function add(uint num) public view returns(uint){num += 1;  //对函数形参进行修改,但是函数形参仅存储在内存,也就是memory,当函数执行完成,形参随之被销毁return num;}function test() public view returns(uint,uint){uint i = 2;  //这是在函数内部定义的变量,也存储在内存memory中,当函数执行完成也会被销毁uint j =  add(i);  //把i作为参数传入add函数中,add函数会为i建立副本,在add中对生成的形参副本进行修改,不会影响i本身的值return(i,j);}
}

(1)所有的复杂类型,即数组、结构和映射类型,都有一个额外属性——“数据位置”,用来说明数据是保存在内存memory中还是存储storage中,保存在memory中的数据,在函数执行完毕后空间会被释放,而保存在storage中的数据会随合约一直存储在区块链上。

(2)根据上下文不同,大多数时候数据有默认的位置,但也可以通过在类型名后增加关键字storage或 memory 进行修改。

(3)函数参数(包括返回的参数)的数据位置默认是 memory,局部变量的数据位置默认是memory,状态变量的数据位置强制是storage。

(4)另外还存在第三种数据位置——calldata ,这是一块只读的,且不会永久存储的位置,用来存储函数参数;外部函数的参数(非返回参数)的数据位置被强制指定为 calldata ,效果跟 memory 差不多。

(5)公开可见(publicly visible)的函数参数一定是 memory 类型,如果要求是 storage 类型 则必须是 private 或者 internal 函数,这是为了防止随意的公开调用占用资源。

2、storage引用:

pragma solidity ^0.5.17;contract StorageTest
{uint[] arrx;  //这个变量定义在storage中,也就是随合约写在区块链中function test(uint[] memory arry) public returns(uint)  //用memory修饰的变量,定义在内存中,它可以在函数体内部正常使用,和一般的变量没多少区别{arrx = arry;   //把内存中的arry赋给区块链中的arrx,arrx会被改变uint[] storage z = arrx;  //在函数体内部定义一个可变长度的数组时,若声明是storage类型(该版本编译器没有默认storage,必须声明)//它就相当于一个指针(或者C++中的引用),指向区块链上的arrx,当修改z的时候,实际上操作的是区块链上的arrx(仅限于数组、mapping类型和结构体有这种语法)z[0] = 100;  //实际上修改了区块链上的arrxz.length = 100;  //实际上修改了区块链上arrx的长度return z[0];
}// 返回arrx的第一个元素function test2() public returns(uint){return arrx[0];}// 返回arrx的长度function test3() public returns(uint){return arrx.length;}}

3、结构体:

(1)定义及初始化:

pragma solidity ^0.5.17;contract StructTest
{//定义一个结构体(在合约内部定义)struct Student{string name;uint grade;//Student student;  与其它语言一样,禁止结构体内部包含自己(否则创建结构体时会无限开辟空间)//Student[] student;  不过结构体中可以定义自己的动态长度数组,其初始长度为0,不会无限开辟空间//mapping(uint=>Student) Map;  //通过mapping也可以包含自己}function init() public view returns(string memory,uint){// 初始化方式一Student memory s = Student("lalala",100);  //函数体内部创建结构体必须加memory,否则会认为这是创建一个指向storage中结构体的指针,会报错(动态长度数组同理)return(s.name,s.grade);}function init2() public view returns(string memory,uint){// 初始化方式二   Student memory s = Student({name:"lalala",grade:100});//在初始化结构体时可以带上变量的名称return(s.name,s.grade);}}

(2)mapping特性:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;uint grade;mapping(uint=>string) Map;  }Student s2;function init() public returns(string memory,uint){//结构体中存在mapping时,初始化结构体可以忽视mappingStudent memory s = Student("lalala",100);//但是memory类型结构体对象是不能直接操作mapping属性变量的// s.Map[0] = "wawawa";//这时可以在函数体外部创建一个变量,把内存中的s复制给外部的变量,通过外部变量进行操作s2 = s;s2.Map[0] = "wawawa";return(s2.name,s2.grade);}
}

(3)结构体作为函数参数:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;uint grade;}//结构体作为函数参数时,函数必须用internal修饰function test(Student memory student) internal{Student memory stu = student;  //结构体作为形参不能直接赋值给storage类型的结构体,除非形参中的结构体也用storage修饰}
}

4、结构体中storage和memory的类型转换:

(1)storage=>storage:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;string grade;}Student student;  //合约状态变量的类型为storagefunction getStudent(Student storage stu) internal returns(Student memory){Student storage stu1 = stu;  //函数体内部定义指针,指向传入的函数形参,而函数形参stu又指向状态变量student(也可看作是C++中的引用)stu1.name = "lalala";stu1.grade = "10000";  //通过stu1指针(也可以理解为C++中的引用)能修改状态变量studentreturn stu1;}function test() public returns(string memory) {return getStudent(student).name;  //所调用的函数形参是storage类型,可以通过编译}
}

(2)memory=>storage:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;string grade;}Student student;function getStudent(Student memory stu) internal returns(Student memory){student = stu;  //直接将传进函数的结构体stu拷贝到状态变量student中stu.name = "lalala";  //修改函数形参,对tmp以及student都不会有影响stu.grade = "100";//student = stu;  如果在这里再进行拷贝,那么student就会受影响,因为是将修改后的stu拷贝到student中return stu;}function test() public returns(string memory) {Student memory tmp = Student("wangxiaoer","60");  //在函数体内部创建结构体变量getStudent(tmp);  //把在内存中创建的结构体变量当作参数传入函数中return student.name;}
}

(3)storage=>memory:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;string grade;}Student student = Student("wangxiaoer","60");function getStudent(Student storage stu) internal returns(Student memory){Student memory student2 = stu;  //把stu指向(或引用)的student的内容赋给内存中的student2student2.name = "lalala";  //修改内存中的student2,不会影响storage中的studentstudent2.grade = "100";return student2;}function test() public returns(string memory) {getStudent(student);return student.name;}
}

(4)memory=>memory:

pragma solidity ^0.5.17;contract StructTest
{struct Student{string name;string grade;}function getStudent(Student memory stu) internal returns(Student memory){Student memory ter = stu;  //stu是指向内存中meimei的指针,但它却是memory类型,所以ter也是指向meimei的指针ter.name = "lalalalala";  //通过ter竟然可以修改meimeiter.grade = "90";return ter;}function test() public returns(string memory) {Student memory meimei = Student("meimei","3");getStudent(meimei);  //memory实参转给memory形参是指针指向(记住就好,不建议去理解)return meimei.name;}
}

5、枚举体:

pragma solidity ^0.5.17;contract EnumTest
{enum grade{first,second,third}  //定义枚举,first的值为0,second的值为1,以此类推grade mingming = grade.first;  //创建枚举变量function getEnum() public view returns(grade){return mingming;  //返回值为uint8:0}function getEnum2() public view returns(grade){return grade.second;  //返回值为uint8:1}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新鸿蒙HarmonyOS4.0开发登陆的界面2

登陆功能 代码如下: import router from ohos.router; Entry Component struct Index {State message: string XXAPP登陆State userName: string ;State password: string ;build() {Row() {Column({space:50}) {Image($r(app.media.icon)).width(200).interpol…

josef约瑟 静态电压继电器 HWY-41B 19-240V 导轨式安装

HWY-40系列无辅源静态电压继电器 HWY-41A无辅源静态电压继电器 HWY-42A无辅源静态电压继电器 HWY-43A无辅源静态电压继电器 HWY-44A无辅源静态电压继电器 HWY-45A无辅源静态电压继电器 HWY-41B无辅源静态电压继电器 HWY-42B无辅源静态电压继电器 HWY-43B无辅源静态电压继电器 …

Qt之QSlider和QProgressBar

Qt之QSlider和QProgressBar 实验结果 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);connect(ui->dial,&QDial::valueChanged,this,&Widget::do_val…

css设置背景图 路径带括号 不显示问题

我封装了一个组件&#xff0c;用于展示背景图&#xff0c;更具图片比例自适应 <template><divclass"bg-img":style"getBackground(imgSrc)"/> </template><script setup lang"ts"> defineProps<{ imgSrc: string }&…

腾讯云:AI云探索之路

随着科技的飞速发展&#xff0c;人工智能(AI)云计算领域日益显现出其巨大的潜力和价值。在这个充满挑战和机遇的领域&#xff0c;腾讯云凭借其卓越的技术和创新能力&#xff0c;取得了令人瞩目的成果。本文将深入探讨腾讯云在AI云计算领域的优势&#xff0c;以及其为人工智能发…

【概率方法】MCMC 之 Gibbs 采样

上一篇文章讲到&#xff0c;MCMC 中的 HM 算法&#xff0c;它可以解决拒绝采样效率低的问题&#xff0c;但是实际上&#xff0c;当维度高的时候 HM 算法还是在同时处理多个维度&#xff0c;以两个变量 x [ x , y ] \mathbf{x} [x,y] x[x,y] 来说&#xff0c;也就是同时从联合…

值类型相关函数与对象类型相关函数内存调用过程

值类型相关函数内存调用&#xff1a; 先来看这样一段代码&#xff0c;你认为它的运行结果是多少呢&#xff1f; 20和11还是20和10&#xff1f; package org.example;public class Main {public static void main(String[] args) {int a10;add(a);System.out.println(a);}pub…

js Array.every()的使用

2023.12.13今天我学习了如何使用Array.every()的使用&#xff0c;这个方法是用于检测数组中所有存在的元素。 比如我们需要判断这个数组里面的全部元素是否都包含张三&#xff0c;可以这样写&#xff1a; let demo [{id: 1, name: 张三}, {id: 2, name: 张三五}, {id: 3, name…

golang实现同步阻塞、同步非阻塞、异步非阻塞IO模型

一、同步阻塞IO模型TCP和HTTP示例 同步阻塞IO符合我们的直觉认知,应用程序从TCP连接接收数据缓冲区接受数据,如果没有数据就等待——此处就是阻塞,如果有数据需要把数据从内核空间读取到用户空间——此处就是同步。 在Go语言中进行同步阻塞IO编程TCP交互,可以使用标准库中…

一文读懂持续集成和持续部署的差异?

持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;是现代软件开发中的关键实践。虽然它们经常被同时提到并具有共同的目标&#xff0c;但它们的方法、目的和对开发周期的影响是不同的。对于任何寻求根据特定项目需求优化工作流程的开发团队来说&#xf…

我的隐私计算学习——隐私集合求交(2)

笔记内容来自多本书籍、学术资料、白皮书及ChatGPT等工具&#xff0c;经由自己阅读后整理而成。 前篇可见&#xff1a;我的隐私计算学习——隐私集合求交&#xff08;1&#xff09; &#xff08;三&#xff09;PSI应用场景问题 ​在目前的实际应用中&#xff0c;衍生出一些新…

[MySQL]事务原理之redo log,undo log

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 一、log日志文件 &#x1f4d5; 事务执行流程 &#x1f4d5; redo log &#x1f4d5; undo log 二、总结 &#x1f440;再来一遍ACID 1. 原子性&#xff1a;原子性确保事务作为一个整体执行&#xff0c;要么…

Linux操作系统学习(零)、计算机概论

计算机概论 指令集 CPU中含有多种指令集&#xff0c;指令集对于CPU运算具有指导和优化的硬程序&#xff0c;用来引导CPU进行加减运算和控制计算机操作系统的一系列指令的集合 常见的就有微指令集RISC和复杂指令集CISC RISC&#xff1a;包括ARM架构和PPC架构 CISC&#xff…

Nginx【通俗易懂】《中篇》

目录 1.Url重写rewrite 2.防盗链 3.静态资源压缩 4.跨域问题 1.Url重写rewrite &#x1f929;&#x1f929;&#x1f929; 1.1.rewrite书写格式 rewrite是实现URL重写的关键指令&#xff0c;根据regex&#xff08;正则表达式&#xff09;部分内容&#xff0c;重定向到rep…

物联网与低代码:构建智能化的连接世界

物联网&#xff08;IoT&#xff09;是指通过互联网将各种物理设备、传感器、车辆等连接起来&#xff0c;从而实现数据交互和智能化控制的技术领域。而低代码开发平台则是一种快速构建应用程序的方法&#xff0c;通过简化开发过程&#xff0c;使开发人员能够更迅速地实现创意和创…

猫粮哪个牌子质量好性价比高?十大质量好主食冻干猫粮牌子推荐

近年来&#xff0c;冻干猫粮作为备受追捧的高品质猫粮&#xff0c;吸引了越来越多养猫人的关注。新手养猫就弄不明白了&#xff0c;什么是冻干猫粮呢&#xff1f;冻干猫粮可以作为日常主食一直喂吗&#xff1f; 像我这种养猫老司机早就开始了冻干喂养。我把我这些年总结的经验…

linux小知识:使用conda命令操作虚拟环境

写在前面:Conda 是一个开源的软件包管理系统和环境管理系统&#xff0c;分为 anaconda 和 miniconda&#xff0c;本文使用 的是Anaconda&#xff0c;主要是为虚拟环境和安装包的管理 1.激活虚拟环境 conda activate 环境名称2.退出当前虚拟环境 conda deactivate3.查看虚拟环境…

使用openpyxl调整Excel的宽度

逐行加载Excel&#xff0c;并将行宽调整为行中的最大字符数。 希望在打开 Excel 时能够看到所有字符。 失败代码&#xff1a; #失败代码&#xff1a; wb openpyxl.load_workbook(./targetExcelFile.xlsx) ws wb.worksheets[0]for col in ws.iter_cols():max_length 0colum…

Leetcode 46 全排列

题意理解&#xff1a; 首先明确全排列是什么&#xff1f; 使用集合里所有的元素&#xff0c;使用不同的顺序进行排列&#xff0c;所有的排列集合即为全排列。 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 这里的元素不会…

【Jenkins】Centos环境安装Jenkins(通过docker安装)

通过docker环境安装Jenkins 参考官网 https://hub.docker.com/r/jenkins/jenkins/ 1、安装docker环境 # 删除已有安装包 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-…