原文標題:《Solidity 極簡入門: 4. 變量數據存儲和作用域 storage/memory/calldata》
原文作者:0xAA
我最近在重新學 solidity,鞏固一下細節,也寫一個「Solidity 極簡入門」,供小白們使用(編程大佬可以另找教程),每週更新 1-3 講。
所有代碼開源在:github.com/AmazingAng/WTFSolidity
引用類型 (Reference Type):包括數組(array),結構體(struct)和映射(mapping),這類變量佔空間大,賦值時候直接傳遞地址(類似指針)。由於這類變量比較複雜,佔用存儲空間大,我們在使用時必須要聲明數據存儲的位置。
solidity 數據存儲位置有三類:storage,memory 和 calldata。不同存儲位置的 gas 成本不同。storage 類型的數據存在鏈上,類似計算機的硬盤,消耗 gas 多;memory 和 calldata 類型的臨時存在內存裏,消耗 gas 少。大致用法:
1.storage:合約裏的狀態變量默認都是 storage,存儲在鏈上。
2.memory:函數裏的參數和臨時變量一般用 memory,存儲在內存中,不上鍊。
3.calldata:和 memory 類似,存儲在內存中,不上鍊。與 memory 的不同點在於 calldata 變量不能修改(immutable),一般用於函數的參數。例子:

在不同存儲類型相互賦值時候,有時會產生獨立的副本(修改新變量不會影響原變量),有時會產生引用(修改新變量會影響原變量)。規則如下:
1.storage(合約的狀態變量)賦值給本地 storage(函數裏的)時候,會創建引用,改變新變量會影響原變量。例子:

1.storage 賦值給 memory,會創建獨立的複本,修改其中一個不會影響另一個;反之亦然。例子:

1.memory 賦值給 memory,會創建引用,改變新變量會影響原變量。
2.其他情況,變量賦值給 storage,會創建獨立的複本,修改其中一個不會影響另一個。
Solidity 中變量按作用域劃分有三種,分別是狀態變量(state variable),局部變量(local variable)和全局變量 (global variable)
狀態變量是數據存儲在鏈上的變量,所有合約內函數都可以訪問 ,gas 消耗高。狀態變量在合約內、函數外聲明:

我們可以在函數裏更改狀態變量的值:

局部變量是僅在函數執行過程中有效的變量,函數退出後,變量無效。局部變量的數據存儲在內存裏,不上鍊,gas 低。局部變量在函數內聲明:

全局變量是全局範圍工作的變量,都是 solidity 預留關鍵字。他們可以在函數內不聲明直接使用:

在上面例子裏,我們使用了 3 個常用的全局變量:msg.sender, block.number 和 msg.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 值
· now : (uint) 當前塊的時間戳
在第 4 講,我們介紹了 solidity 中的引用類型,數據位置和變量的作用域。重點是 storage, memory 和 calldata 三個關鍵字的用法。他們出現的原因是爲了節省鏈上有限的存儲空間和降低 gas。下一講我們會介紹引用類型中的數組。
原文鏈接
歡迎加入律動 BlockBeats 官方社群:
Telegram 訂閱群:https://t.me/theblockbeats
Telegram 交流群:https://t.me/BlockBeats_App
Twitter 官方帳號:https://twitter.com/BlockBeatsAsia