3. Solidity:變量存儲(chǔ)類型和作用域

3.1 變量存儲(chǔ)類型

引用類型變量占空間大,賦值的時(shí)候直接傳遞地址(類似指針),在使用時(shí)必需聲明數(shù)據(jù)存儲(chǔ)位置。
Solidity中引用類型包括:數(shù)組(array)、結(jié)構(gòu)體(struct)、映射(mapping)。

Solidity數(shù)據(jù)存儲(chǔ)類型有三種:storage、memory、calldata

存儲(chǔ)類型 存儲(chǔ)位置 消耗gas 使用場(chǎng)景
storage 鏈上 狀態(tài)變量
memory 內(nèi)存 函數(shù)參數(shù)、臨時(shí)變量
calldata 內(nèi)存 函數(shù)參數(shù)(不可修改)

calldata一般用于函數(shù)參數(shù),但是是只讀類型,不可修改:

// 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;  // 報(bào)錯(cuò)
        return _x[0];
    }
}

3.2 賦值規(guī)則

在不同存儲(chǔ)類型相互賦值時(shí)候,有時(shí)會(huì)產(chǎn)生獨(dú)立的副本(修改新變量不會(huì)影響原變量),有時(shí)會(huì)產(chǎn)生引用(修改新變量會(huì)影響原變量)。規(guī)則如下:

賦值形式 規(guī)則
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;   // 創(chuàng)建引用
        y[0] = 12; // 修改y會(huì)修改x
    }

    // storage -> memory
    function s2m() external view{
        uint[] memory y = x;    // 創(chuàng)建副本
        y[0] = 23; // 修改y不會(huì)修改x
    }

    // memory -> memory
    function m2m() external pure returns (uint[3] memory) {
        uint[3] memory x1 = [uint(1),2,3]; 
        uint[3] memory y = x1;  // 創(chuàng)建引用
        y[0] = 34; // 修改y會(huì)修改x
        return x1;
    }

    // memory -> storage
    function m2s() external returns (uint[3] memory) {
        uint[3] memory y = [uint(1),2,3]; 
        x = y;  // 創(chuàng)建副本
        x[0] = 45; // 修改x不會(huì)修改y
        return y;
    }
}

3.3 變量作用域

3.3.1 狀態(tài)變量

狀態(tài)變量是數(shù)據(jù)存儲(chǔ)在鏈上的變量,所有合約內(nèi)函數(shù)都可以訪問(wèn) ,gas消耗高。狀態(tài)變量在合約內(nèi)、函數(shù)外聲明:

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

3.3.2 局部變量

局部變量是僅在函數(shù)執(zhí)行過(guò)程中有效的變量,函數(shù)退出后,變量無(wú)效。局部變量的數(shù)據(jù)存儲(chǔ)在內(nèi)存里,不上鏈,gas低。局部變量在函數(shù)內(nèi)聲明:

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

3.3.3 全局變量

全局變量是全局范圍工作的變量,都是solidity預(yù)留關(guān)鍵字。他們可以在函數(shù)內(nèi)不聲明直接使用:

    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個(gè)常用的全局變量:msg.sender, block.numbermsg.data,他們分別代表請(qǐng)求發(fā)起地址,當(dāng)前區(qū)塊高度,和請(qǐng)求數(shù)據(jù)。下面是一些常用的全局變量,更完整的列表請(qǐng)看這個(gè)鏈接

全局變量 類型 說(shuō)明
blockhash(uint blockNumber) bytes32 給定區(qū)塊的哈希值 – 只適用于256最近區(qū)塊, 不包含當(dāng)前區(qū)塊。
block.coinbase address payable 當(dāng)前區(qū)塊礦工的地址
block.gaslimit uint 當(dāng)前區(qū)塊的gaslimit
block.number uint 當(dāng)前區(qū)塊的number
block. timestamp uint 當(dāng)前區(qū)塊的時(shí)間戳,為unix紀(jì)元以來(lái)的秒
gasleft() uint256 剩余 gas
msg. data bytes calldata 完整call data
msg. sender address payable 消息發(fā)送者 (當(dāng)前 caller)
msg. sig bytes4 calldata的前四個(gè)字節(jié) (function identifier)
msg. value uint 當(dāng)前交易發(fā)送的wei值
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容