国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

營銷型網(wǎng)站建設(shè)一般要多少錢產(chǎn)品網(wǎng)絡(luò)營銷策劃方案

營銷型網(wǎng)站建設(shè)一般要多少錢,產(chǎn)品網(wǎng)絡(luò)營銷策劃方案,上海做兼職的網(wǎng)站,網(wǎng)站建設(shè)公司 2018Solidity 是一種靜態(tài)類型語言,這意味著每個(gè)變量(狀態(tài)變量和局部變量)都需要在編譯時(shí)指定變量的類型。 “undefined”或“null”值的概念在Solidity中不存在,但是新聲明的變量總是有一個(gè) 默認(rèn)值 ,具體的默認(rèn)值跟類型相…

Solidity 是一種靜態(tài)類型語言,這意味著每個(gè)變量(狀態(tài)變量和局部變量)都需要在編譯時(shí)指定變量的類型。

“undefined”或“null”值的概念在Solidity中不存在,但是新聲明的變量總是有一個(gè) 默認(rèn)值 ,具體的默認(rèn)值跟類型相關(guān)。 要處理任何意外的值,應(yīng)該使用 錯(cuò)誤處理 來恢復(fù)整個(gè)交易,或者返回一個(gè)帶有第二個(gè) bool 值的元組表示成功。

值類型

以下類型也稱為值類型,因?yàn)檫@些類型的變量將始終按值來傳遞。 也就是說,當(dāng)這些變量被用作函數(shù)參數(shù)或者用在賦值語句中時(shí),總會(huì)進(jìn)行值拷貝。

布爾類型

bool :可能的取值為字面常量值 true 和 false

運(yùn)算符:

! (邏輯非)
&& (邏輯與, “and” )
|| (邏輯或, “or” )
== (等于)
!= (不等于)

整型

int / uint :分別表示有符號和無符號的不同位數(shù)的整型變量。 支持關(guān)鍵字 uint8 到 uint256 (無符號,從 8 位到 256 位)以及 int8 到 int256,以 8 位為步長遞增。 uint 和 int 分別是 uint256 和 int256 的別名。

運(yùn)算符:

比較運(yùn)算符: <= , < , == , != , >= , > (返回布爾值)
位運(yùn)算符: & , | , ^ (異或), ~ (位取反)
移位運(yùn)算符: << (左移位) , >> (右移位)
算數(shù)運(yùn)算符: + , - , 一元運(yùn)算負(fù) - (僅針對有符號整型), * , / , % (取余或叫模運(yùn)算) , ** (冪)

對于整形 X,可以使用 type(X).min 和 type(X).max 去獲取這個(gè)類型的最小值與最大值。

0.8.0 開始,算術(shù)運(yùn)算有兩個(gè)計(jì)算模式:一個(gè)是 “wrapping”(截?cái)?#xff09;模式或稱 “unchecked”(不檢查)模式,一個(gè)是”checked” (檢查)模式。 默認(rèn)情況下,算術(shù)運(yùn)算在 “checked” 模式下,即都會(huì)進(jìn)行溢出檢查,如果結(jié)果落在取值范圍之外,調(diào)用會(huì)通過 失敗異常 回退。 你也可以通過 unchecked { … } 切換到 “unchecked”模式

比較運(yùn)算

位運(yùn)算

位運(yùn)算在數(shù)字的二進(jìn)制補(bǔ)碼表示上執(zhí)行。 這意味著: ~int256(0)== int256(-1)

移位

移位操作的結(jié)果具有左操作數(shù)的類型,同時(shí)會(huì)截?cái)嘟Y(jié)果以匹配類型。 右操作數(shù)必須是無符號類型。 嘗試按帶符號的類型移動(dòng)將產(chǎn)生編譯錯(cuò)誤。

    x << y 等于數(shù)學(xué)表達(dá)式 x * 2 ** y。x >> y 等于數(shù)學(xué)表達(dá)式 x / 2 ** y , 四舍五入到負(fù)無窮。

對于移位操作不會(huì)像算術(shù)運(yùn)算那樣執(zhí)行溢出檢查,其結(jié)果總是被截?cái)唷?/strong>

加、減、乘法運(yùn)算

表達(dá)式 -x 相當(dāng)于 (T(0) - x) 這里 T 是指 x 的類型。 -x 只能應(yīng)用在有符號型的整數(shù)上。 如果 x 為負(fù)數(shù), -x 為正數(shù)。 由于使用兩進(jìn)制補(bǔ)碼表示數(shù)據(jù),你還需要小心:

如果有 int x = type(int).min;, 那 -x 將不在正數(shù)取值的范圍內(nèi)。 這意味著這個(gè)檢測 unchecked { assert(-x == x); } 是可以通過的(即這種情況下,不能假設(shè)它的負(fù)數(shù)會(huì)是正數(shù)),如果是 checked 模式,則會(huì)觸發(fā)異常。

除法運(yùn)算

除法運(yùn)算結(jié)果的類型始終是其中一個(gè)操作數(shù)的類型,整數(shù)除法總是產(chǎn)生整數(shù)。 在Solidity中,分?jǐn)?shù)會(huì)取零。 這意味著 int256(-5) / int256(2) == int256(-2) 。

除以0 會(huì)發(fā)生 Panic 錯(cuò)誤 , 而且這個(gè)檢查,不可以通過 unchecked { … } 禁用掉。

模運(yùn)算(取余)

模運(yùn)算 a%n 是在操作數(shù) a 的除以 n 之后產(chǎn)生余數(shù) r ,其中 q = int(a / n) 和 r = a - (n * q) 。 這意味著模運(yùn)算結(jié)果與左操作數(shù)相同的符號相同(或零)。 對于 負(fù)數(shù)的a : a % n == -(-a % n), 幾個(gè)例子:

int256(5) % int256(2) == int256(1)
int256(5) % int256(-2) == int256(1)
int256(-5) % int256(2) == int256(-1)
int256(-5) % int256(-2) == int256(-1)

冪運(yùn)算

冪運(yùn)算僅適用于無符號類型。 結(jié)果的類型總是等于基數(shù)的類型. 請注意類型足夠大以能夠容納冪運(yùn)算的結(jié)果,要么發(fā)生潛在的assert異常或者使用截?cái)嗄J健?/p>

x**3 的例子,表達(dá)式 xxx 也許更便宜。 在任何情況下,都建議進(jìn)行 gas 消耗測試和使用優(yōu)化器。

定長浮點(diǎn)型

Solidity 還沒有完全支持定長浮點(diǎn)型??梢月暶鞫ㄩL浮點(diǎn)型的變量,但不能給它們賦值或把它們賦值給其他變量。。

地址類型 Address

地址類型有兩種形式,他們大致相同:

    address:保存一個(gè)20字節(jié)的值(以太坊地址的大小)。address payable :可支付地址,與 address 相同,不過有成員函數(shù) transfer 和 send 。

這種區(qū)別背后的思想是 address payable 可以向其發(fā)送以太幣,而不能先一個(gè)普通的 address 發(fā)送以太幣,例如,它可能是一個(gè)智能合約地址,并且不支持接收以太幣。

類型轉(zhuǎn)換:

允許從 address payable 到 address 的隱式轉(zhuǎn)換,而從 address 到 address payable 必須顯示的轉(zhuǎn)換, 通過 payable(

) 進(jìn)行轉(zhuǎn)換。

地址類型成員變量

balance 和 transfer 成員

可以使用 balance 屬性來查詢一個(gè)地址的余額, 也可以使用 transfer 函數(shù)向一個(gè)可支付地址(payable address)發(fā)送 以太幣 (以 wei 為單位):

address x = 0x123;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);

如果當(dāng)前合約的余額不夠多,則 transfer 函數(shù)會(huì)執(zhí)行失敗,或者如果以太轉(zhuǎn)移被接收帳戶拒絕, transfer 函數(shù)同樣會(huì)失敗而進(jìn)行回退。

如果 x 是一個(gè)合約地址,它的代碼(更具體來說是, 如果有receive函數(shù), 執(zhí)行 receive 接收以太函數(shù), 或者存在fallback函數(shù),執(zhí)行 Fallback 回退函數(shù) 函數(shù))會(huì)跟 transfer 函數(shù)調(diào)用一起執(zhí)行(這是 EVM 的一個(gè)特性,無法阻止)。 如果在執(zhí)行過程中用光了 gas 或者因?yàn)槿魏卧驁?zhí)行失敗,以太幣 交易會(huì)被打回,當(dāng)前的合約也會(huì)在終止的同時(shí)拋出異常。

send 成員

send 是 transfer 的低級版本。如果執(zhí)行失敗,當(dāng)前的合約不會(huì)因?yàn)楫惓6K止,但 send 會(huì)返回 false。

在使用 send 的時(shí)候會(huì)有些風(fēng)險(xiǎn):如果調(diào)用棧深度是 1024 會(huì)導(dǎo)致發(fā)送失敗(這總是可以被調(diào)用者強(qiáng)制),如果接收者用光了 gas 也會(huì)導(dǎo)致發(fā)送失敗。 所以為了保證 以太幣 發(fā)送的安全,一定要檢查 send 的返回值,使用 transfer 或者更好的辦法: 使用接收者自己取回資金的模式

call, delegatecall 和 staticcall

為了與不符合 應(yīng)用二進(jìn)制接口 的合約交互,或者要更直接地控制編碼,提供了函數(shù) calldelegatecallstaticcall 。 它們都帶有一個(gè) bytes memory 參數(shù)和返回執(zhí)行成功狀態(tài)(bool)和數(shù)據(jù)(bytes memory)。

函數(shù) abi.encode,abi.encodePacked,abi.encodeWithSelector 和 abi.encodeWithSignature 可用于編碼結(jié)構(gòu)化數(shù)據(jù)。

bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");
(bool success, bytes memory returnData) = address(nameReg).call(payload);
require(success);

可以使用 gas 修改器 調(diào)整提供的 gas 數(shù)量:

address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName"));

delegatecall 的目的是使用另一個(gè)合約中的庫代碼。 用戶必須確保兩個(gè)合約中的存儲結(jié)構(gòu)都適合委托調(diào)用 (delegatecall)。

從以太坊拜占庭(byzantium)版本開始 提供了 staticcall ,它與 call 基本相同,但如果被調(diào)用的函數(shù)以任何方式修改狀態(tài)變量,都將回退。

所有三個(gè)函數(shù) call , delegatecall 和 staticcall 都是非常低級的函數(shù),應(yīng)該只把它們當(dāng)作 最后一招 來使用,因?yàn)樗鼈兤茐牧?Solidity 的類型安全性。

所有三種方法都提供 gas 選項(xiàng),而 value 選項(xiàng)僅 call 支持 。

code 和 codehash 成員

你可以查詢?nèi)魏沃悄芎霞s的部署代碼。使用 .code 來獲取EVM的字節(jié)碼,其返回 bytes memory ,值可能是空。 使用 .codehash 獲得該代碼的 Keccak-256哈希值 (為 bytes32 )。注意, addr.codehash 比使用 keccak256(addr.code) 更便宜。

所有合約都可以轉(zhuǎn)換為 address 類型,因此可以使用 address(this).balance 查詢當(dāng)前合約的余額。

合約類型

每一個(gè) contract 定義都有他自己的類型。

您可以隱式地將合約轉(zhuǎn)換為從他們繼承的合約。 合約可以顯式轉(zhuǎn)換為 address 類型。

只有當(dāng)合約具有 接收receive函數(shù) 或 payable 回退函數(shù)時(shí),才能顯式和 address payable 類型相互轉(zhuǎn)換 轉(zhuǎn)換仍然使用 address(x) 執(zhí)行, 如果合約類型沒有接收或payable 回退功能,則可以使用 payable(address(x)) 轉(zhuǎn)換為 address payable 。

合約不支持任何運(yùn)算符。

合約類型的成員是合約的外部函數(shù)及 public 的 狀態(tài)變量。

對于合約 C 可以使用 type? 獲取合約的類型信息

定長字節(jié)數(shù)組

關(guān)鍵字有:bytes1, bytes2, bytes3, …, bytes32。

運(yùn)算符:

比較運(yùn)算符: <=, <, ==, !=, >=, > (返回布爾型)
位運(yùn)算符: &, |, ^ (按位異或), ~ (按位取反)
移位運(yùn)算符: << (左移位), >> (右移位)
索引訪問:如果 x 是 bytesI 類型,那么 x[k] (其中 0 <= k < I)返回第 k 個(gè)字節(jié)(只讀)。

該類型可以和作為右操作數(shù)的無符號整數(shù)類型進(jìn)行移位運(yùn)算(但返回結(jié)果的類型和左操作數(shù)類型相同),右操作數(shù)表示需要移動(dòng)的位數(shù)。 進(jìn)行有符號整數(shù)位移運(yùn)算會(huì)引發(fā)運(yùn)行時(shí)異常

變長字節(jié)數(shù)組

bytes: 變長字節(jié)數(shù)組,參見 數(shù)組。它并不是值類型。
string: 變長 UTF-8 編碼字符串類型,參見 數(shù)組。并不是值類型。

地址字面常量

比如像 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF 這樣的通過了地址校驗(yàn)和測試的十六進(jìn)制字面常量會(huì)作為 address 類型。 而沒有通過校驗(yàn)測試, 長度在 39 到 41 個(gè)數(shù)字之間的十六進(jìn)制字面常量,會(huì)產(chǎn)生一個(gè)錯(cuò)誤,您可以在零前面添加(對于整數(shù)類型)或在零后面添加(對于bytesNN類型)以消除錯(cuò)誤。

字符串字面常量及類型

字符串字面常量是指由雙引號或單引號引起來的字符串( “foo” 或者 ‘bar’)。 它們也可以分為多個(gè)連續(xù)的部分( “foo” “bar” 等效于 “foobar”),這在處理長字符串時(shí)很有用。 不像在 C 語言中那樣帶有結(jié)束符; “foo” 相當(dāng)于 3 個(gè)字節(jié)而不是 4 個(gè)。 和整數(shù)字面常量一樣,字符串字面常量的類型也可以發(fā)生改變,

但它們可以隱式地轉(zhuǎn)換成 bytes1,……, bytes32,如果合適的話,還可以轉(zhuǎn)換成 bytes 以及 string。

例如: bytes32 samevar = “stringliteral” 字符串字面常量在賦值給 bytes32 時(shí)被解釋為原始的字節(jié)形式。

字符串字面常量支持下面的轉(zhuǎn)義字符:

\<newline> (轉(zhuǎn)義實(shí)際換行)
\\ (反斜杠)
\' (單引號)
\" (雙引號)
\b (退格)
\f (換頁)
\n (換行符)
\r (回車)
\t (標(biāo)簽 tab)
\v (垂直標(biāo)簽)
\xNN (十六進(jìn)制轉(zhuǎn)義,見下文)
\uNNNN (unicode 轉(zhuǎn)義,見下文)

Unicode 字面常量

常規(guī)字符串文字只能包含ASCII,而Unicode文字(以關(guān)鍵字unicode為前綴)可以包含任何有效的UTF-8序列。 它們還支持與轉(zhuǎn)義序列完全相同的字符作為常規(guī)字符串文字。

string memory a = unicode"Hello 😃";

十六進(jìn)制字面常量

十六進(jìn)制字面常量以關(guān)鍵字 hex 打頭,后面緊跟著用單引號或雙引號引起來的字符串(例如,hex"001122FF" )。 字符串的內(nèi)容必須是一個(gè)十六進(jìn)制的字符串,它們的值將使用二進(jìn)制表示。

枚舉類型

枚舉是在Solidity中創(chuàng)建用戶定義類型的一種方法。 它們是顯示所有整型相互轉(zhuǎn)換,但不允許隱式轉(zhuǎn)換。 從整型顯式轉(zhuǎn)換枚舉,會(huì)在運(yùn)行時(shí)檢查整數(shù)時(shí)候在枚舉范圍內(nèi),否則會(huì)導(dǎo)致異常( Panic異常 )。 枚舉需要至少一個(gè)成員,默認(rèn)值是第一個(gè)成員,枚舉不能多于 256 個(gè)成員。

數(shù)據(jù)表示與C中的枚舉相同:選項(xiàng)從“0”開始的無符號整數(shù)值表示。

使用 type(NameOfEnum).min 和 type(NameOfEnum).max 你可以得到給定枚舉的最小值和最大值。

用戶定義的值類型

一個(gè)用戶定義的值類型允許在一個(gè)基本的值類型上創(chuàng)建一個(gè)零成本的抽象。 這類似于一個(gè)別名,但有更嚴(yán)格的類型要求。

用戶定義值類型使用 type C is V 來定義,其中 C 是新引入的類型的名稱, V 必須是內(nèi)置的值類型(”底層類型”)。 函數(shù) C.wrap 被用來從底層類型轉(zhuǎn)換到自定義類型。同樣地,函數(shù)函數(shù) C.unwrap 用于從自定義類型轉(zhuǎn)換到底層類型。

type UFixed256x18 is uint256;

函數(shù)類型

函數(shù)類型是一種表示函數(shù)的類型。可以將一個(gè)函數(shù)賦值給另一個(gè)函數(shù)類型的變量,也可以將一個(gè)函數(shù)作為參數(shù)進(jìn)行傳遞,還能在函數(shù)調(diào)用中返回函數(shù)類型變量。 函數(shù)類型有兩類: - 內(nèi)部(internal) 函數(shù)類型 - 外部(external) 函數(shù)類型。

內(nèi)部函數(shù)只能在當(dāng)前合約內(nèi)被調(diào)用(更具體來說,在當(dāng)前代碼塊內(nèi),包括內(nèi)部庫函數(shù)和繼承的函數(shù)中),因?yàn)樗鼈儾荒茉诋?dāng)前合約上下文的外部被執(zhí)行。 調(diào)用一個(gè)內(nèi)部函數(shù)是通過跳轉(zhuǎn)到它的入口標(biāo)簽來實(shí)現(xiàn)的,就像在當(dāng)前合約的內(nèi)部調(diào)用一個(gè)函數(shù)。

外部函數(shù)由一個(gè)地址和一個(gè)函數(shù)簽名組成,可以通過外部函數(shù)調(diào)用傳遞或者返回。

function () {internal|external} [pure|constant|view|payable] [returns ()]

與參數(shù)類型相反,返回類型不能為空 —— 如果函數(shù)類型不需要返回,則需要?jiǎng)h除整個(gè) returns () 部分。

函數(shù)類型默認(rèn)是內(nèi)部函數(shù),因此不需要聲明 internal 關(guān)鍵字。

類型轉(zhuǎn)換:

函數(shù)類型 A 可以隱式轉(zhuǎn)換為函數(shù)類型 B 當(dāng)且僅當(dāng): 它們的參數(shù)類型相同,返回類型相同,它們的內(nèi)部/外部屬性是相同的,并且 A 的狀態(tài)可變性比 B 的狀態(tài)可變性更具限制性,比如:

pure 函數(shù)可以轉(zhuǎn)換為 view 和 non-payable 函數(shù)
view 函數(shù)可以轉(zhuǎn)換為 non-payable 函數(shù)
payable 函數(shù)可以轉(zhuǎn)換為 non-payable 函數(shù)

public(或 external)函數(shù)都有下面的成員:

.address 返回函數(shù)的合約地址。
.selector 返回 ABI 函數(shù)選擇器

引用類型

引用類型可以通過多個(gè)不同的名稱修改它的值

引用類型包括結(jié)構(gòu),數(shù)組和映射,如果使用引用類型,則必須明確指明數(shù)據(jù)存儲哪種類型的位置(空間)里:

內(nèi)存 即數(shù)據(jù)在內(nèi)存中,因此數(shù)據(jù)僅在其生命周期內(nèi)(函數(shù)調(diào)用期間)有效。不能用于外部調(diào)用。
存儲 狀態(tài)變量保存的位置,只要合約存在就一直存儲.
調(diào)用數(shù)據(jù) 用來保存函數(shù)參數(shù)的特殊數(shù)據(jù)位置,是一個(gè)只讀位置。

數(shù)據(jù)位置

所有的引用類型,如 數(shù)組 和 結(jié)構(gòu)體 類型,都有一個(gè)額外注解 數(shù)據(jù)位置 ,來說明數(shù)據(jù)存儲位置。

有三種位置: 內(nèi)存memory 、 存儲storage 以及 調(diào)用數(shù)據(jù) calldata。

調(diào)用數(shù)據(jù) 是不可修改的、非持久的函數(shù)參數(shù)存儲區(qū)域,效果大多類似 內(nèi)存 。 主要用于外部函數(shù)的參數(shù),但也可用于其他變量。

數(shù)據(jù)位置與賦值行為

在 存儲 和 內(nèi)存 之間兩兩賦值(或者從 調(diào)用數(shù)據(jù) 賦值 ),都會(huì)創(chuàng)建一份獨(dú)立的拷貝。
從 內(nèi)存 到 內(nèi)存 的賦值只創(chuàng)建引用, 這意味著更改內(nèi)存變量,其他引用相同數(shù)據(jù)的所有其他內(nèi)存變量的值也會(huì)跟著改變。
從 存儲 到本地存儲變量的賦值也只分配一個(gè)引用。
其他的向 存儲 的賦值,總是進(jìn)行拷貝。 這種情況的示例如對狀態(tài)變量或 存儲 的結(jié)構(gòu)體類型的局部變量成員的賦值,即使局部變量本身是一個(gè)引用,也會(huì)進(jìn)行一份拷貝(譯者注:查看下面 ArrayContract 合約 更容易理解)。

數(shù)組

數(shù)組可以在聲明時(shí)指定長度,也可以動(dòng)態(tài)調(diào)整大小(長度)。

一個(gè)元素類型為 T,固定長度為 k 的數(shù)組可以聲明為 T[k],而動(dòng)態(tài)數(shù)組聲明為 T[]。

可以使用 .push() 方法在末尾追加一個(gè)新元素,其中 .push() 追加一個(gè)零初始化的元素并返回對它的引用。

bytes 和 string 也是數(shù)組
bytes 和 string 類型的變量是特殊的數(shù)組。
bytes 類似于 bytes1[],但它在 調(diào)用數(shù)據(jù) 和 內(nèi)存 中會(huì)被“緊打包”(譯者注:將元素連續(xù)地存在一起,不會(huì)按每 32 字節(jié)一單元的方式來存放)。
string 與 bytes 相同,但不允許用長度或索引來訪問。

函數(shù) bytes.concat 和 string.concat

可以使用 string.concat 連接任意數(shù)量的 string 字符串。 該函數(shù)返回一個(gè) string memory ,包含所有參數(shù)的內(nèi)容,無填充方式拼接在一起。 如果你想使用不能隱式轉(zhuǎn)換為 string 的其他類型作為參數(shù),你需要先把它們轉(zhuǎn)換為 string。

同樣, bytes.concat 函數(shù)可以連接任意數(shù)量的 bytes 或 bytes1 … bytes32 值。 該函數(shù)返回一個(gè) bytes memory ,包含所有參數(shù)的內(nèi)容,無填充方式拼接在一起。

創(chuàng)建內(nèi)存數(shù)組

可使用 new 關(guān)鍵字在 內(nèi)存 中基于運(yùn)行時(shí)創(chuàng)建動(dòng)態(tài)長度數(shù)組。 與 存儲 數(shù)組相反的是,你 不能 通過修改成員變量 .push 改變 內(nèi)存 數(shù)組的大小。

必須提前計(jì)算所需的大小或者創(chuàng)建一個(gè)新的內(nèi)存數(shù)組并復(fù)制每個(gè)元素。

在Solidity中的所有變量,新分配的數(shù)組元素總是以 默認(rèn)值 初始化。

pragma solidity >=0.4.16 <0.9.0;contract TX {function f(uint len) public pure {uint[] memory a = new uint[](7);bytes memory b = new bytes(len);assert(a.length == 7);assert(b.length == len);a[6] = 8;}
}

數(shù)組常量

它總是一個(gè)靜態(tài)大小的內(nèi)存數(shù)組,其長度為表達(dá)式的數(shù)量。

數(shù)組的基本類型是列表上的第一個(gè)表達(dá)式的類型。

[1, 2, 3] 的類型是 uint8[3] memory。 因?yàn)槊總€(gè)常量的類型都是 uint8 ,如果你希望結(jié)果是 uint[3] memory 類型,你需要將第一個(gè)元素轉(zhuǎn)換為 uint 。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;contract LBC {function f() public pure {g([uint(1), 2, 3]);}function g(uint[3] memory) public pure {// ...}
}

數(shù)組常量 [1, -1] 是無效的,因?yàn)榈谝粋€(gè)表達(dá)式類型是 uint8 而第二個(gè)類似是 int8 他們不可以隱式的相互轉(zhuǎn)換。 為了確保可以運(yùn)行,你是可以使用例如: [int8(1), -1] 。

如果要初始化動(dòng)態(tài)長度的數(shù)組,則必須顯示給各個(gè)元素賦值:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;contract C {function f() public pure {uint[] memory x = new uint[](3);x[0] = 1;x[1] = 3;x[2] = 4;}
}

數(shù)組成員

  • length: 數(shù)組有 length 成員變量表示當(dāng)前數(shù)組的長度。 一經(jīng)創(chuàng)建,內(nèi)存 數(shù)組的大小就是固定的(但卻是動(dòng)態(tài)的,也就是說,它可以根據(jù)運(yùn)行時(shí)的參數(shù)創(chuàng)建)。
  • push():動(dòng)態(tài)的 存儲 數(shù)組以及 bytes 類型( string 類型不可以)都有一個(gè) push() 的成員函數(shù),它用來添加新的零初始化元素到數(shù)組末尾,并返回元素引用. 因此可以這樣:  x.push().t = 2 或 x.push() = b.
  • push(x):動(dòng)態(tài)的 存儲 數(shù)組以及 bytes 類型( string 類型不可以)都有一個(gè) push(x) 的成員函數(shù),用來在數(shù)組末尾添加一個(gè)給定的元素,這個(gè)函數(shù)沒有返回值.
  • pop():變長的 存儲 數(shù)組以及 bytes 類型( string 類型不可以)都有一個(gè) pop() 的成員函數(shù), 它用來從數(shù)組末尾刪除元素。 同樣的會(huì)在移除的元素上隱含調(diào)用 delete ,這個(gè)函數(shù)沒有返回值。

對存儲數(shù)組元素的懸空引用

當(dāng)使用存儲數(shù)組時(shí),你需要注意避免懸空的引用。 懸空引用是指一個(gè)指向不再存在的東西的引用,或者是對象被移除而沒有更新引用。 例如,如果你將一個(gè)數(shù)組元素的引用存儲在一個(gè)局部的引用中,然后從包含數(shù)組中 .pop() 出來,就會(huì)發(fā)生懸空引用。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;contract C {uint[][] s;function f() public {// 保存s最后一個(gè)元素的指向。uint[] storage ptr = s[s.length - 1];//  移除 s 最后一個(gè)元素s.pop();// 向不再屬于數(shù)組的元素寫入數(shù)據(jù)ptr.push(0x42);// 現(xiàn)在添加元素到 ``s`` 不會(huì)添加一個(gè)空元素, 而是數(shù)組長度為 1``0x42`` 作為其元素。s.push();assert(s[s.length - 1][0] == 0x42);}
}

ptr.push(0x42) 寫入 不 會(huì)回退, 盡管 ptr 不再指向有效的 s 元素, 由于編譯器假定未使用的存儲空間總是被清零的, 所以隨后的 s.push() 不會(huì)明確地將零寫入存儲空間。 所以在 push() 之后, s 的最后一個(gè)元素的長度是 1 ,并且包含 0x42 作為第一個(gè)元素。 0x42作為其第一個(gè)元素。

數(shù)組切片

數(shù)組切片是數(shù)組連續(xù)部分的視圖,用法如:x[start:end] , start 和 end 是 uint256 類型(或結(jié)果為 uint256 的表達(dá)式)。 x[start:end] 的第一個(gè)元素是 x[start] , 最后一個(gè)元素是 x[end - 1] 。

如果 start 比 end 大或者 end 比數(shù)組長度還大,將會(huì)拋出異常。

start 和 end 都可以是可選的: start 默認(rèn)是 0, 而 end 默認(rèn)是數(shù)組長度。

結(jié)構(gòu)體

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;// 定義的新類型包含兩個(gè)屬性。
// 在合約外部聲明結(jié)構(gòu)體可以使其被多個(gè)合約共享。 在這里,這并不是真正需要的。
struct Funder {address addr;uint amount;
}contract CrowdFunding {// 也可以在合約內(nèi)部定義結(jié)構(gòu)體,這使得它們僅在此合約和衍生合約中可見。struct Campaign {address beneficiary;uint fundingGoal;uint numFunders;uint amount;mapping (uint => Funder) funders;}
}

映射

映射類型在聲明時(shí)的形式為 mapping(KeyType => ValueType)。 其中 KeyType 可以是任何基本類型,即可以是任何的內(nèi)建類型, bytes 和 string 或合約類型、枚舉類型。 而其他用戶定義的類型或復(fù)雜的類型如:映射、結(jié)構(gòu)體、即除 bytes 和 string 之外的數(shù)組類型是不可以作為 KeyType 的類型的。

可迭代映射

映射本身是無法遍歷的,即無法枚舉所有的鍵。不過,可以在它們之上實(shí)現(xiàn)一個(gè)數(shù)據(jù)結(jié)構(gòu)來進(jìn)行迭代。 例如,以下代碼實(shí)現(xiàn)了 IterableMapping 庫,然后 User 合約可以添加數(shù)據(jù), sum 函數(shù)迭代求和所有值。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.8;struct IndexValue { uint keyIndex; uint value; }
struct KeyFlag { uint key; bool deleted; }struct itmap {mapping(uint => IndexValue) data;KeyFlag[] keys;uint size;
}type Iterator is uint;library IterableMapping {function insert(itmap storage self, uint key, uint value) internal returns (bool replaced) {uint keyIndex = self.data[key].keyIndex;self.data[key].value = value;if (keyIndex > 0)return true;else {keyIndex = self.keys.length;self.keys.push();self.data[key].keyIndex = keyIndex + 1;self.keys[keyIndex].key = key;self.size++;return false;}}function remove(itmap storage self, uint key) internal returns (bool success) {uint keyIndex = self.data[key].keyIndex;if (keyIndex == 0)return false;delete self.data[key];self.keys[keyIndex - 1].deleted = true;self.size --;}function contains(itmap storage self, uint key) internal view returns (bool) {return self.data[key].keyIndex > 0;}function iterateStart(itmap storage self) internal view returns (Iterator) {return iteratorSkipDeleted(self, 0);}function iterateValid(itmap storage self, Iterator iterator) internal view returns (bool) {return Iterator.unwrap(iterator) < self.keys.length;}function iterateNext(itmap storage self, Iterator iterator) internal view returns (Iterator) {return iteratorSkipDeleted(self, Iterator.unwrap(iterator) + 1);}function iterateGet(itmap storage self, Iterator iterator) internal view returns (uint key, uint value) {uint keyIndex = Iterator.unwrap(iterator);key = self.keys[keyIndex].key;value = self.data[key].value;}function iteratorSkipDeleted(itmap storage self, uint keyIndex) private view returns (Iterator) {while (keyIndex < self.keys.length && self.keys[keyIndex].deleted)keyIndex++;return Iterator.wrap(keyIndex);}
}// 如何使用
contract User {// Just a struct holding our data.itmap data;// Apply library functions to the data type.using IterableMapping for itmap;// Insert somethingfunction insert(uint k, uint v) public returns (uint size) {// This calls IterableMapping.insert(data, k, v)data.insert(k, v);// We can still access members of the struct,// but we should take care not to mess with them.return data.size;}// Computes the sum of all stored data.function sum() public view returns (uint s) {for (Iterator i = data.iterateStart();data.iterateValid(i);i = data.iterateNext(i)) {(, uint value) = data.iterateGet(i);s += value;}}
}

三元運(yùn)算符

三元運(yùn)算符是一個(gè)表達(dá)是形式: <expression> ? <trueExpression> : <falseExpression>

復(fù)合操作及自增自減操作

如果 a 是一個(gè) LValue(即一個(gè)變量或者其它可以被賦值的東西),以下運(yùn)算符都可以使用簡寫:

a += e 等同于 a = a + e。其它運(yùn)算符如 -=, *=, /=, %=, |=, &= , ^= , <<= 和 >>= 都是如此定義的。 a++ 和 a-- 分別等同于 a += 1 和 a -= 1,但表達(dá)式本身的值等于 a 在計(jì)算之前的值。 與之相反, --a 和 ++a 雖然最終 a 的結(jié)果與之前的表達(dá)式相同,但表達(dá)式的返回值是計(jì)算之后的值。

delete

delete a 的結(jié)果是將 a 類型初始值賦值給 a。即對于整型變量來說,相當(dāng)于 a = 0,delete 也適用于數(shù)組,對于動(dòng)態(tài)數(shù)組來說,是將重置為數(shù)組長度為0的數(shù)組,而對于靜態(tài)數(shù)組來說,是將數(shù)組中的所有元素重置為初始值。對數(shù)組而言, delete a[x] 僅刪除數(shù)組索引 x 處的元素,其他的元素和長度不變,這以為著數(shù)組中留出了一個(gè)空位。如果打算刪除項(xiàng),映射可能是更好的選擇。

如果對象 a 是結(jié)構(gòu)體,則將結(jié)構(gòu)體中的所有屬性(成員)重置。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;contract DeleteLBC {uint data;uint[] dataArray;function f() public {uint x = data;delete x; // 將 x 設(shè)為 0,并不影響數(shù)據(jù)delete data; // 將 data 設(shè)為 0,并不影響 x,因?yàn)樗匀挥袀€(gè)副本uint[] storage y = dataArray;delete dataArray;// 將 dataArray.length 設(shè)為 0,但由于 uint[] 是一個(gè)復(fù)雜的對象,y 也將受到影響,// 因?yàn)樗且粋€(gè)存儲位置是 storage 的對象的別名。// 另一方面:"delete y" 是非法的,引用了 storage 對象的局部變量只能由已有的 storage 對象賦值。assert(y.length == 0);}
}

顯式轉(zhuǎn)換

如果某些情況下編譯器不支持隱式轉(zhuǎn)換,但是你很清楚你要做的結(jié)果,這種情況可以考慮顯式轉(zhuǎn)換。 注意這可能會(huì)發(fā)生一些無法預(yù)料的后果,因此一定要進(jìn)行測試,確保結(jié)果是你想要的! 下面的示例是將一個(gè) int8 類型的負(fù)數(shù)轉(zhuǎn)換成 uint:

int8 y = -3;
uint x = uint(y);

這段代碼的最后, x 的值將是 0xfffff…fd (64 個(gè) 16 進(jìn)制字符),因?yàn)檫@是 -3 的 256 位補(bǔ)碼形式。

http://aloenet.com.cn/news/34371.html

相關(guān)文章:

  • 做網(wǎng)站寫需求千萬不要做手游推廣員
  • 誠信通開了網(wǎng)站誰給做精準(zhǔn)的搜索引擎優(yōu)化
  • 網(wǎng)站建設(shè)公司該怎么銷售最新收錄查詢
  • 手機(jī)網(wǎng)站如何做新區(qū)快速seo排名
  • 滄州百度愛采購灰色詞seo推廣
  • 企業(yè)網(wǎng)站排名提升軟件能優(yōu)化谷歌排名推廣公司
  • 如何給網(wǎng)站做seo怎么制作網(wǎng)站?
  • 新鄭做網(wǎng)站佛山網(wǎng)站建設(shè)公司
  • 東莞公司注冊代理青島網(wǎng)站seo服務(wù)
  • 政務(wù)服務(wù)網(wǎng)站 建設(shè)方案百度競價(jià)開戶渠道
  • css做網(wǎng)站常用網(wǎng)站seo優(yōu)化服務(wù)
  • 微信小程序注冊需要多少錢南昌seo管理
  • 有贊可以做獨(dú)立網(wǎng)站嗎百度關(guān)鍵詞推廣多少錢
  • 電子商務(wù)書店網(wǎng)站設(shè)計(jì)實(shí)驗(yàn)競價(jià)排名的服務(wù)模式是
  • 通用網(wǎng)址查詢網(wǎng)站網(wǎng)絡(luò)營銷項(xiàng)目
  • 胖哥網(wǎng)站的建設(shè)目標(biāo)網(wǎng)絡(luò)廣告投放渠道有哪些
  • 成都網(wǎng)站制作公司湘潭網(wǎng)站設(shè)計(jì)
  • 3小時(shí)網(wǎng)站建設(shè)平臺seo診斷優(yōu)化方案
  • asp網(wǎng)站開發(fā)環(huán)境同仁seo排名優(yōu)化培訓(xùn)
  • 網(wǎng)站備案現(xiàn)狀網(wǎng)絡(luò)平臺建站
  • 使用wordpress版權(quán)深圳市seo上詞多少錢
  • 對網(wǎng)站備案的認(rèn)識網(wǎng)絡(luò)營銷的主要傳播渠道
  • 網(wǎng)站開發(fā)投入產(chǎn)出分析國際新聞最新消息戰(zhàn)爭
  • 網(wǎng)頁游戲傳奇霸主輔助寧波seo優(yōu)化公司排名
  • 濱州網(wǎng)站建設(shè)公司軍事新聞今日最新消息
  • 谷歌有做網(wǎng)站建設(shè)怎樣做推廣是免費(fèi)的
  • 外國人做的中國字網(wǎng)站推廣軟件的渠道有哪些
  • seo搜索引擎優(yōu)化興盛優(yōu)選寧波seo快速優(yōu)化平臺
  • 長治網(wǎng)站建設(shè)招聘聚合搜索引擎
  • 安徽省外經(jīng)建設(shè)集團(tuán)有限公司網(wǎng)站b站推廣