美文网首页
3. Solidity:变量存储类型和作用域

3. Solidity:变量存储类型和作用域

作者: 泡泡龙吐泡泡 | 来源:发表于2023-09-24 12:30 被阅读0次

3.1 变量存储类型

引用类型变量占空间大,赋值的时候直接传递地址(类似指针),在使用时必需声明数据存储位置
Solidity中引用类型包括:数组(array)、结构体(struct)、映射(mapping)

Solidity数据存储类型有三种:storage、memory、calldata

存储类型 存储位置 消耗gas 使用场景
storage 链上 状态变量
memory 内存 函数参数、临时变量
calldata 内存 函数参数(不可修改)

calldata一般用于函数参数,但是是只读类型,不可修改:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract VarStorage {

    // calldata
    function fcalldata(uint[] calldata _x) pure external returns (uint) {
        // calldata 为只读类型,不能修改
        // _x[0] = 1;  // 报错
        return _x[0];
    }
}

3.2 赋值规则

在不同存储类型相互赋值时候,有时会产生独立的副本(修改新变量不会影响原变量),有时会产生引用(修改新变量会影响原变量)。规则如下:

赋值形式 规则
storage -> storage 引用
storage -> memory 副本
memory -> memory 引用
memory -> storage 副本
  • 代码示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract V2VRule {
    uint[] public x = [1,2,3];

    // storage -> storage
    function s2s() external {
        uint[] storage y = x;   // 创建引用
        y[0] = 12; // 修改y会修改x
    }

    // storage -> memory
    function s2m() external view{
        uint[] memory y = x;    // 创建副本
        y[0] = 23; // 修改y不会修改x
    }

    // memory -> memory
    function m2m() external pure returns (uint[3] memory) {
        uint[3] memory x1 = [uint(1),2,3]; 
        uint[3] memory y = x1;  // 创建引用
        y[0] = 34; // 修改y会修改x
        return x1;
    }

    // memory -> storage
    function m2s() external returns (uint[3] memory) {
        uint[3] memory y = [uint(1),2,3]; 
        x = y;  // 创建副本
        x[0] = 45; // 修改x不会修改y
        return y;
    }
}

3.3 变量作用域

3.3.1 状态变量

状态变量是数据存储在链上的变量,所有合约内函数都可以访问 ,gas消耗高。状态变量在合约内、函数外声明:

contract Variables {
    uint public x = 1;
    uint public y;
    string public z;
}

3.3.2 局部变量

局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存储在内存里,不上链,gas低。局部变量在函数内声明:

    function bar() external pure returns(uint){
        uint xx = 1;
        uint yy = 3;
        uint zz = xx + yy;
        return(zz);
    }

3.3.3 全局变量

全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:

    function global() external view returns(address, uint, bytes memory){
        address sender = msg.sender;
        uint blockNum = block.number;
        bytes memory data = msg.data;
        return(sender, blockNum, data);
    }

在上面例子里,我们使用了3个常用的全局变量:msg.sender, block.numbermsg.data,他们分别代表请求发起地址,当前区块高度,和请求数据。下面是一些常用的全局变量,更完整的列表请看这个链接

全局变量 类型 说明
blockhash(uint blockNumber) bytes32 给定区块的哈希值 – 只适用于256最近区块, 不包含当前区块。
block.coinbase address payable 当前区块矿工的地址
block.gaslimit uint 当前区块的gaslimit
block.number uint 当前区块的number
block. timestamp uint 当前区块的时间戳,为unix纪元以来的秒
gasleft() uint256 剩余 gas
msg. data bytes calldata 完整call data
msg. sender address payable 消息发送者 (当前 caller)
msg. sig bytes4 calldata的前四个字节 (function identifier)
msg. value uint 当前交易发送的wei值

相关文章

  • 从零开始复习Java-变量、常量、作用域

    变量(Variable) Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。 变量作用域 ...

  • C语言函数定义域

    作用域:起作用的区域变量按作用域分:局部变量:定义在函数内部的变量全局变量 :定义在函数外部的变量变量按存储类型分...

  • [C] C语言static关键字总结

    《C和指针》第二版 P44-45 C语言的变量具有3种特征,作用域,链接属性,存储类型。4种作用域:文件作用域,...

  • Solidity - 变量作用域

    2018-10-25笔记 代码块 代码块指的就是{}所围成的代码,也就是从{开始,到}结束,花括号里面的所有的代码...

  • JS回顾变量、作用域、内存问题

    基本类型和引用类型的值属性的动态复制变量值传递参数检测类型 执行环境与作用域延长作用域链没有块级作用域声明变量提升...

  • C++基础

    1.C++基本语法、注释、数据类型、变量作用域、常量 2.c++存储类 3.运算符 4.循环和判断 5.函数 6....

  • JS高级(第三版)第4章知识点总结

    变量、作用域和内存问题 1.理解基本类型和引用类型的值2.理解执行环境3.理解垃圾收集 变量 1.JS的变量为松散...

  • js总结(5.作用域)

    作用域 1.变量的作用域 2.函数作用域的变量 3.全局作用域的变量 4.注意 5.声明提前:

  • Java基础

    二、变量 定义: 1.变量是程序中最基础的存储单元,其要素包括变量名、变量类型和作用域; 2.变量其实是内存中的一...

  • ECMA知识点

    变量、作用域和内存问题 变量基本类型值和引用类型值 执行环境和作用域当代码在一个环境中执行时,会创建变量对象的一个...

网友评论

      本文标题:3. Solidity:变量存储类型和作用域

      本文链接:https://www.haomeiwen.com/subject/lyyfbdtx.html