首页 > 其他分享 >3、数据类型中的数据位置,stograge、memory、calldata

3、数据类型中的数据位置,stograge、memory、calldata

时间:2022-10-04 21:11:04浏览次数:53  
标签:calldata 存储 stograge 数据类型 位置 storage memory 状态变量 数据

数据位置

所有的复杂类型,即 数组 和 结构 类型,都有一个额外属性,“数据位置”,说明数据是保存在 内存memory 中还是 存储storage 中。 根据上下文不同,大多数时候数据有默认的位置,但也可以通过在类型名后增加关键字 storage 或 memory 进行修改。 函数参数(包括返回的参数)的数据位置默认是 memory, 局部变量的数据位置默认是 storage,状态变量的数据位置强制是 storage (这是显而易见的)。

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

数据位置的指定非常重要,因为它们影响着赋值行为: 在 存储storage 和 内存memory 之间两两赋值,或者 存储storage 向状态变量(甚至是从其它状态变量)赋值都会创建一份独立的拷贝。 然而状态变量向局部变量赋值时仅仅传递一个引用,而且这个引用总是指向状态变量,因此后者改变的同时前者也会发生改变。 另一方面,从一个 内存memory 存储的引用类型向另一个 内存memory 存储的引用类型赋值并不会创建拷贝。

复制代码
pragma solidity ^0.4.0;

contract C {
    uint[] x; // x 的数据存储位置是 storage

    // memoryArray 的数据存储位置是 memory
    function f(uint[] memoryArray) public {
        x = memoryArray; // 将整个数组拷贝到 storage 中,可行
        var y = x;  // 分配一个指针(其中 y 的数据存储位置是 storage),可行
        y[7]; // 返回第 8 个元素,可行
        y.length = 2; // 通过 y 修改 x,可行
        delete x; // 清除数组,同时修改 y,可行
        // 下面的就不可行了;需要在 storage 中创建新的未命名的临时数组, /
        // 但 storage 是“静态”分配的:
        // y = memoryArray;
        // 下面这一行也不可行,因为这会“重置”指针,
        // 但并没有可以让它指向的合适的存储位置。
        // delete y;

        g(x); // 调用 g 函数,同时移交对 x 的引用
        h(x); // 调用 h 函数,同时在 memory 中创建一个独立的临时拷贝
    }

    function g(uint[] storage storageArray) internal {}
    function h(uint[] memoryArray) public {}
}
复制代码

  总结

强制指定的数据位置:
  • 外部函数的参数(不包括返回参数): calldata
  • 状态变量: storage
默认数据位置:
  • 函数参数(包括返回参数): memory
  • 所有其它局部变量: storage

深入分析

storage 存储结构是在合约创建的时候就确定好了的,它取决于合约所声明状态变量。但是内容可以被(交易)调用改变。

Solidity 称这个为状态改变,这也是合约级变量称为状态变量的原因。也可以更好的理解为什么状态变量都是storage存储。

memory 只能用于函数内部,memory 声明用来告知EVM在运行时创建一块(固定大小)内存区域给变量使用。

storage 在区块链中是用key/value的形式存储,而memory则表现为字节数组

关于栈(stack)

EVM是一个基于栈的语言,栈实际是在内存(memory)的一个数据结构,每个栈元素占为256位,栈最大长度为1024。 值类型的局部变量是存储在栈上。

不同存储的消耗(gas消耗)

  • storage 会永久保存合约状态变量,开销最大

  • memory 仅保存临时变量,函数调用之后释放,开销很小

  • stack 保存很小的局部变量,几乎免费使用,但有数量限制。

标签:calldata,存储,stograge,数据类型,位置,storage,memory,状态变量,数据
From: https://www.cnblogs.com/shyroke/p/16754498.html

相关文章

  • 变量 + 数据类型
    变量:什么是变量?一个可以存储数据(存储的地方在内存中),并可以在代码的运行中,给与数据的改变注意:变量的声明必须在最前面语法:数据类型变量名称=值;案例:%d-输出一个......
  • 2、solidity数据类型以及函数
    solidity数据类型分为以下几种:1、整型int(有符号整型,有正有负)uint(无符号整型,无负数)以8位为区间,支持int8,int16,int24至int256,uint同理。int默认为int256,uint......
  • 数据类型
    publicclassDemo{publicstaticvoidmain(String[]args){inti=10;inti2=010;inti3=0x1A;//16进制0-9A-Finti4=0b0010;......
  • 0458-Hive数据类型校验问题分析
    温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。Fayson的github:​​https://github.com/fayson/cdhproject​​提示:代码块部分可......
  • 注释、标识符和关键字、数据类型及其拓展
    注释、标识符和关键字publicclassHelloWorld{publicstaticvoidmain(String[]args){//单行注释//输出一个Hello,World!System.ou......
  • vscode中快速声明数据类型
    如何快速声明数据类型上面这张图letobj1=reactive({listArr:[],backArr:[{name:'张三',age:10,info:'本科'}],age:100,name:'',flag:......
  • 第八篇: go 变量、常量、基本数据类型
    变量/*###########变量的定义和使用##########*/packagemainfuncmain(){ //1方式一:基本定义 //var关键字变量名变量类型=变量值 //varageint=18//定......
  • 第十二篇: go数据类型
    数据类型1.分类Go语言内置以下这些基础类型:类型名称长度零值说明bool布尔类型1false其值不为真即为家,不可以用数字代表true或falsebyte字节型10......
  • 数据类型转换
    1.为变量赋值时,赋值数据类型和变量的类型应为一致。如果不一样系统则会转变变量的类型然后再赋值,这叫自动类型转换。2当变量类型时int类型时a.如果超出范围(21亿)则会随机赋值......
  • 003.JavaScript的数据类型
         ......