在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ 類型
簡介
編程規(guī)范
雜項
源文件的布局
單位和全局可用變量
合約的結(jié)構(gòu)
通用模式
常見問題
深入理解 Solidity
安裝Solidity
智能合約介紹
合約
Solidity 編程實例
http://solidity.readthedocs.io/en/latest/security-considerations
類型
表達(dá)式和控制結(jié)構(gòu)

類型

Solidity是一種靜態(tài)類型語言,意思是每個變量(聲明和本地)在編譯時刻都要定義 (或者至少要知曉,參看 后面的類型導(dǎo)出 )。

Solidity提供幾個基本類型組合成復(fù)雜類型。

變量類型

以下類型被叫做值類型,因為這些類型的變量總是要被賦值,作為函數(shù)參數(shù)或者在賦值中,總需要拷貝。

布爾類型

布爾:可能的常量值 是 真或假

操作符:

  • !(邏輯非)

  • &&(邏輯與,“and")

  • ||?? (邏輯或,”or“)

  • ==(相等)

  • !=(不等)

  • 操作符||和&&可以應(yīng)用常規(guī)短路規(guī)則,即 表達(dá)式?f(x) || g(y), 如果f(x) 已是真,g(y)將不用計算,即使它有副作用 (真||任意值 均為真,假&&任意布爾值 均為假)。

整型

int? / uint?: 是有符號和無符號的整數(shù),關(guān)鍵字uint8 到 uint256 步長8 (從8到256位的無符號整數(shù) )

?uint 和 int 分別是 uint256 和 int256的別名

操作符:

  • 比較 : <=,<,==,!=,>=,> (計算布爾量)

  • 位操作符: &,|,^(位異或),~(位取反)

  • 算術(shù)操作符:+,-,一元-,一元+,*,/,%(取余數(shù)),**(冪次方)

地址

地址: 20字節(jié)(一個??Ethereum地址),地址的類型也可以有成員(請看地址功能?(#functions-on-addresses))? 作為所有合約的base

操作符:

  • <=, <, ==, !=, >= 和 >

地址成員:

  • 賬戶余額(balance)和發(fā)送(send)

若查詢到有資產(chǎn)余額的地址,然后發(fā)送? Ether(以wei為單位) 到send 函數(shù)的地址上

address?x?=?0x123;

address?myAddress?=?this;

if?(x.balance?<?10?&&?myAddress.balance?>=?10) x.send(10);

注解

如果x是合約地址,它的代碼(特別的指出 如果有回退函數(shù),) 將和send 調(diào)用一起執(zhí)行(這是EVM的限制,不能修改) 如果用完了gas或者失敗,Ether轉(zhuǎn)移將被回退,這種情況下,send返回false

  • 調(diào)用(call)和調(diào)用碼( callcode)

另外,和合約的接口不是附在ABI 上,函數(shù)調(diào)用可以引用任意數(shù)量的參數(shù),這些參數(shù)要填補成32字節(jié),并被拼接。一個例外的情況是第一個參數(shù)被確切的編碼成4字節(jié),這種情況下,不用填補,直接使用函數(shù)符號

address?nameReg?=?0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;

nameReg.call("register", "MyName");

nameReg.call(bytes4(sha3("fun(uint256)")), a);

函數(shù)調(diào)用返回了一個布爾值,表示函數(shù)是否是正常調(diào)用結(jié)束(true)或引起了EVM異常(false)。不可能訪問返回實際數(shù)據(jù)(這個我們需要提前知道編碼和大小)。

同樣,可以使用函數(shù)callcode:不同之處在于,只使用給定地址的編碼,所有其他方面(存儲、余額…)取自于當(dāng)前的合約。callcode的目的是使用庫代碼存儲在另一個合同。用戶必須確保存儲在兩個合約的布局適用于callcode。

call和callcode是非常低級的函數(shù),它可以作為打破Solidity的類型安全的最后手段。

  • call and callcode

請注意

所有合同繼承成員地址,所以可以使用this.balance查詢當(dāng)前合約的余額。

Fixed-size byte arrays

bytes1, bytes2, bytes3, ..., bytes32. byte is an alias for bytes1.

Operators:
  • Comparisons: <=, <, ==, !=, >=, > (evaluate to bool)

  • Bit operators: &, |, ^ (bitwise exclusive or), ~ (bitwise negation)

固定大小的字節(jié)數(shù)組

bytes1, bytes2, bytes3, ..., bytes32. byte 都是 bytes1的別名.

操作符:

  • 比較符?: <=, <, ==, !=, >=, > (布爾的評估)

  • 位操作符;: &, |, ^ (按位置異或),~(按位取反)

動態(tài)分配大小字節(jié)數(shù)組:

bytes:動態(tài)分配大小字節(jié)數(shù)組,參看 Arrays,不是一個值類型!

string:動態(tài)大小UTF8編碼的字符串,參看Arrays。不是一個值類型!

????? 作為一個常識, 使用bytes來表示任意長度原始字節(jié)數(shù)據(jù),使用string來表示特定長度字符串?dāng)?shù)據(jù)(utf - 8編碼)。如果你想限定特定數(shù)量的字節(jié)長度, 就使用bytes1 到 bytes32,? 因為這樣占用的存儲空間更少。

整型常量

整型常量是特定精度整數(shù),它們也可以和非常量同時使用。例如, var x = 1 - 2;? 1 - 2的值是-1,然后賦值給x, 這時x接收類型為int8——最小的類型,其中包含-1, 雖然1和2的類型實際上是uint8。

有時最大超過256位的整型常量也可用于計算:var x =(0 xffffffffffffffffffff 0 xffffffffffffffffffff) 0;這里,x的值是0,它的類型是uint8類型。

字符串常量

字符串常量用兩個雙引號括起來(“abc”)。和整型常量相比,字符串常量有些不同,字符串常量可以隱式轉(zhuǎn)換成bytes ???? 如果合適,可以是bytes,也可以是string。

contract?test {

????enum?ActionChoices { GoLeft, GoRight, GoStraight, SitStill }

??? ActionChoices choice;

??? ActionChoices?constant?defaultChoice?=?ActionChoices.GoStraight;

????function?setGoStraight()

??? {

??????? choice?=?ActionChoices.GoStraight;

??? }

枚舉是一種Solidity中的創(chuàng)建一個用戶定義的類型。枚舉類型中的枚舉值可顯式轉(zhuǎn)換,但從整數(shù)類型隱式轉(zhuǎn)換是不允許的。

contract?test {

????enum?ActionChoices { GoLeft, GoRight, GoStraight, SitStill }

??? ActionChoices choice;

??? ActionChoices?constant?defaultChoice?=?ActionChoices.GoStraight;

????function?setGoStraight()

??? {

??????? choice?=?ActionChoices.GoStraight;

??? }

????// Since enum types are not part of the ABI, the signature of "getChoice"

????// will automatically be changed to "getChoice() returns (uint8)"

????// for all matters external to Solidity. The integer type used is just

????// large enough to hold all enum values, i.e. if you have more values,

????// `uint16` will be used and so on.

/ /因為枚舉類型不是ABI的一部分,“getChoice”的符號

/ /將自動改為“getChoice()返回(uint8)”

/ /從Solidity外部看,使用的整數(shù)類型

/ /足夠容納所有枚舉值,但如果你有更多的值,

/ /“uint16”將使用。

????function?getChoice()?returns?(ActionChoices)

??? {

????????return?choice;

??? }

????function?getDefaultChoice()?returns?(uint)

??? {

????????return?uint(defaultChoice);

??? }}

引用類型

復(fù)雜類型,例如類型并不總是適合256位,比我們已經(jīng)看到的值類型更復(fù)雜的類型,必須更仔細(xì)地處理。因為復(fù)制拷貝他們可能相當(dāng)耗費存儲和時間,? 我們必須考慮把它們存儲在內(nèi)存(這不是持久化)或者存儲器(狀態(tài)變量存放的地方)。

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

每一個復(fù)雜類型,即數(shù)組和結(jié)構(gòu)體,有一個額外的注解,“數(shù)據(jù)位置”,不管它是存儲在內(nèi)存中,還是存儲在存儲器上。根據(jù)上下文,總是有一個默認(rèn)的,但它可以通過附加存儲或內(nèi)存覆蓋類型。函數(shù)參數(shù)的默認(rèn)值(包括返回參數(shù))是在內(nèi)存上,局部變量的默認(rèn)存儲位置是在存儲器上。存儲器上存有狀態(tài)變量(很明顯)。

(除了內(nèi)存,存儲器這兩個位置之外),還有第三個數(shù)據(jù)位置,“calldata”,這是一個?無法改變的,非持久的?存儲函數(shù)參數(shù)的地方。外部函數(shù)的函數(shù)參數(shù)(不返回參數(shù))“calldata”,其在形式上象內(nèi)存。

數(shù)據(jù)位置很重要,因為它們改變賦值方式:在存儲和內(nèi)存以及狀態(tài)變量之間賦值(甚至從其他狀態(tài)變量)總是創(chuàng)建一個獨立的副本。賦值只分配一個本地存儲變量引用,這總是指向狀態(tài)變量的引用,后者同時改變。另一方面,從一個內(nèi)存存儲引用類型, 賦值到另一個內(nèi)存存儲引用類型,(這時)并不創(chuàng)建一個副本。

contract?c {

??uint[] x;?// the data location of x is storage

??// the data location of memoryArray is memory

??function?f(uint[] memoryArray) {

??? x?=?memoryArray;?// works, copies the whole array to storage

????var?y?=?x;?// works, assigns a pointer, data location of y is storage

??? y[7];?// fine, returns the 8th element

??? y.length?=?2;?// fine, modifies x through y

????delete?x;?// fine, clears the array, also modifies y

????// The following does not work; it would need to create a new temporary /

????// unnamed array in storage, but storage is "statically" allocated:

????// y = memoryArray;

????// This does not work either, since it would "reset" the pointer, but there

????// is no sensible location it could point to.

????// delete y;

??? g(x);?// calls g, handing over a reference to x

??? h(x);?// calls h and creates an independent, temporary copy in memory

? }

??function?g(uint[]?storage?storageArray)?internal?{}

??function?h(uint[] memoryArray) {}}

contract?c {

??uint[] x;?// the data location of x is storage????x的數(shù)據(jù)位置是存儲器

??// the data location of memoryArray is memory??memoryArray的數(shù)據(jù)位置是內(nèi)存

??function?f(uint[] memoryArray) {

??? x?=?memoryArray;?// works, copies the whole array to storage??運行,拷貝整個數(shù)組到存儲器

????var?y?=?x;?// works, assigns a pointer, data location of y is storage?運行,賦值到一個指針,y的數(shù)據(jù)位置是存儲器

??? y[7];?// fine, returns the 8th element?好了,返回第8個元素

??? y.length?=?2;?// fine, modifies x through y????好了,通過y改變x

????delete?x;?// fine, clears the array, also modifies y??好了,清除數(shù)組,也改變y

????// The following does not work; it would need to create a new temporary /??以下代碼不起作用, 它是在存儲中創(chuàng)立一個臨時的未命名的數(shù)組,但存儲器是“靜態(tài)”分配的

????// unnamed array in storage, but storage is "statically" allocated:

????// y = memoryArray;

????// This does not work either, since it would "reset" the pointer, but there?這個也不起作用,因為 它重置了指針, 但已經(jīng)沒有相應(yīng)的位置可以指向

????// is no sensible location it could point to.

????// delete y;

??? g(x);?// calls g, handing over a reference to x???調(diào)用g(x)? 將x作為引用

??? h(x);?// calls h and creates an independent, temporary copy in memory?調(diào)用h(x). 在內(nèi)存中創(chuàng)立了一個獨立的,暫時的拷貝

? }

??function?g(uint[]?storage?storageArray)?internal?{}

??function?h(uint[] memoryArray) {}}

總結(jié)

強制數(shù)據(jù)位置:

  • 外部函數(shù)的參數(shù)(不返回):calldata

  • 狀態(tài)變量:存儲器

默認(rèn)數(shù)據(jù)位置:

  • 函數(shù)(有返回)的參數(shù):內(nèi)存

  • 其他所有局部變量:存儲器

數(shù)組

數(shù)組是可以在編譯時固定大小的,也可以是動態(tài)的。對于存儲器數(shù)組來說,成員類型可以是任意的(也可以是其他數(shù)組,映射或結(jié)構(gòu))。對于內(nèi)存數(shù)組來說 ,成員類型不能是一個映射;如果是公開可見的函數(shù)參數(shù),成員類型是必須是ABI類型的。

固定大小k的數(shù)組和基本類型T,可以寫成T[k],? 動態(tài)數(shù)組寫成 T[ ] 。例如, 有5個基本類型為uint 的動態(tài)數(shù)組的數(shù)組 可以寫成uint[ ][5]? ( 注意,和一些其他語言相比,這里的符號表示次序是反過來的)。為了訪問第三動態(tài)數(shù)組中的第二個uint, 必須使用x[2][1](下標(biāo)是從零開始的,訪問模式和聲明模式正好相反, 即x[2]是從右邊剔除了一階)。

bytes和?string?是特殊類型的數(shù)組。?bytes?類似于byte[ ],但它是緊湊排列在calldata里的。string?等于?bytes ,?但不允許用長度或所以索引訪問(現(xiàn)在情況是這樣的)。

所以bytes應(yīng)該優(yōu)先于byte[ ],因為它效率更高。

請注意

如果你想訪問字符串s的某個字節(jié),? 要使用 bytes(s).length/bytes(s)[7]= ' x ';。記住,你正在訪問的低級utf - 8字節(jié)表示,而不是單個字符!

成員(函數(shù)):

length: 總有 一個稱作length的成員(函數(shù))來存放元素的數(shù)量。動態(tài)數(shù)組可以通過改變.length成員(函數(shù)),在存儲器里來調(diào)整大小(不是在內(nèi)存中)。當(dāng)試圖訪問現(xiàn)有長度之外的成員時,這并不是自動被許可的。(數(shù)組)一旦創(chuàng)建,內(nèi)存里的數(shù)組大小是固定的(如果是動態(tài)的數(shù)組,則取決于運行時參數(shù))。

push?:動態(tài)存儲數(shù)組arrays和字節(jié)bytes(不是字符串string)有一個成員函數(shù)稱作push,可在數(shù)組的尾部添加一個元素。函數(shù)返回新的長度。

警告

到目前為止,還不可以在外部函數(shù)中使用數(shù)組的數(shù)組。

警告

由于EVM的局限,不可能從外部函數(shù)調(diào)用返回的動態(tài)內(nèi)容。合約函數(shù)f contract C { function f() returns (uint[]) { ... } }? 使用web3.js調(diào)用,將有返回值,? 但使用Solidity調(diào)用,就沒有返回值。

現(xiàn)在唯一的解決方法是使用較大的靜態(tài)尺寸大小的數(shù)組。

contract?ArrayContract {

??uint[2*\*20] m_aLotOfIntegers;

??// Note that the following is not a pair of arrays but an array of pairs.

??bool[2][] m_pairsOfFlags;

??// newPairs is stored in memory - the default for function arguments

??function?setAllFlagPairs(bool[2][] newPairs) {

????// assignment to a storage array replaces the complete array

??? m_pairsOfFlags?=?newPairs;

? }

??function?setFlagPair(uint?index,?bool?flagA,?bool?flagB) {

????// access to a non-existing index will throw an exception

??? m_pairsOfFlags[index][0]?=?flagA;

??? m_pairsOfFlags[index][1]?=?flagB;

? }

??function?changeFlagArraySize(uint?newSize) {

????// if the new size is smaller, removed array elements will be cleared

??? m_pairsOfFlags.length?=?newSize;

? }

??function?clear() {

????// these clear the arrays completely

????delete?m_pairsOfFlags;

????delete?m_aLotOfIntegers;

????// identical effect here

??? m_pairsOfFlags.length?=?0;

? }

??bytes?m_byteData;

??function?byteArrays(bytes?data) {

????// byte arrays ("bytes") are different as they are stored without padding,

????// but can be treated identical to "uint8[]"

??? m_byteData?=?data;

??? m_byteData.length?+=?7;

??? m_byteData[3]?=?8;

????delete?m_byteData[2];

? }

??function?addFlag(bool[2] flag)?returns?(uint) {

????return?m_pairsOfFlags.push(flag);

? }

??function?createMemoryArray(uint?size)?returns?(bytes) {

????// Dynamic memory arrays are created using `new`:

????uint[2][]?memory?arrayOfPairs?=?new?uint[2][](size);

????// Create a dynamic byte array:

????bytes?memory?b?=?new?bytes(200);

????for?(uint?i?=?0; i?<?b.length; i++)

????? b[i]?=?byte(i);

????return?b;

? }}

contract?ArrayContract {

??uint[2\20] m_aLotOfIntegers;

??// Note that the following is not a pair of arrays but an array of pairs.?注意下面不是兩個數(shù)組,而是一個數(shù)組,該數(shù)組的成員是一對值

??bool[2][] m_pairsOfFlags;

??// newPairs is stored in memory - the default for function arguments??newPairs在內(nèi)存中存儲-這是函數(shù)參數(shù)的缺省方式

??function?setAllFlagPairs(bool[2][] newPairs) {

????// assignment to a storage array replaces the complete array?賦值到一個存儲器數(shù)組里以替換整個數(shù)組

??? m_pairsOfFlags?=?newPairs;

? }

??function?setFlagPair(uint?index,?bool?flagA,?bool?flagB) {

????// access to a non-existing index will throw an exception

??? m_pairsOfFlags[index][0]?=?flagA;

??? m_pairsOfFlags[index][1]?=?flagB;

? }

??function?changeFlagArraySize(uint?newSize) {

????// if the new size is smaller, removed array elements will be cleared??如果新的尺寸太小,則已經(jīng)移除的元素將被清除

??? m_pairsOfFlags.length?=?newSize;

? }

??function?clear() {

????// these clear the arrays completely

????delete?m_pairsOfFlags;

????delete?m_aLotOfIntegers;

????// identical effect here

??? m_pairsOfFlags.length?=?0;

? }

??bytes?m_byteData;

??function?byteArrays(bytes?data) {

????// byte arrays ("bytes") are different as they are stored without padding,??如果沒有填充的話,字節(jié)數(shù)組("bytes")和存儲時是不同的

????// but can be treated identical to "uint8[]"??但可以轉(zhuǎn)換成 "uint8[]"

??? m_byteData?=?data;

??? m_byteData.length?+=?7;

??? m_byteData[3]?=?8;

????delete?m_byteData[2];

? }

??function?addFlag(bool[2] flag)?returns?(uint) {

????return?m_pairsOfFlags.push(flag);

? }

??function?createMemoryArray(uint?size)?returns?(bytes) {

????// Dynamic memory arrays are created using `new`:?使用`new`創(chuàng)立動態(tài)內(nèi)存數(shù)組

????uint[2][]?memory?arrayOfPairs?=?new?uint[2][](size);

????// Create a dynamic byte array:??創(chuàng)立動態(tài) byte 數(shù)組

????bytes?memory?b?=?new?bytes(200);

????for?(uint?i?=?0; i?<?b.length; i++)

????? b[i]?=?byte(i);

????return?b;

? }}

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

Solidity 提供了一種方法來定義新類型的形式結(jié)構(gòu),如下面的例子所示:

contract?CrowdFunding {

??// Defines a new type with two fields.

??struct?Funder {

????address?addr;

????uint?amount;

? }

??struct?Campaign {

????address?beneficiary;

????uint?fundingGoal;

????uint?numFunders;

????uint?amount;

????mapping?(uint?=>?Funder) funders;

? }

??uint?numCampaigns;

??mapping?(uint?=>?Campaign) campaigns;

??function?newCampaign(address?beneficiary,?uint?goal)?returns?(uint?campaignID) {

??? campaignID?=?numCampaigns++;?// campaignID is return variable

????// Creates new struct and saves in storage. We leave out the mapping type.

??? campaigns[campaignID]?=?Campaign(beneficiary, goal, 0, 0);

? }

??function?contribute(uint?campaignID) {

??? Campaign c?=?campaigns[campaignID];

????????// Creates a new temporary memory struct, initialised with the given values

????????// and copies it over to storage.

????????// Note that you can also use Funder(msg.sender, msg.value) to initialise.

??? c.funders[c.numFunders++]?=?Funder({addr:?msg.sender, amount:?msg.value});

??? c.amount?+=?msg.value;

? }

??function?checkGoalReached(uint?campaignID)?returns?(bool?reached) {

??? Campaign c?=?campaigns[campaignID];

????if?(c.amount?<?c.fundingGoal)

??????return?false;

??? c.beneficiary.send(c.amount);

??? c.amount?=?0;

????return?true;

? }}

contract?CrowdFunding {

??// Defines a new type with two fields.?定義了兩個域的新類型

??struct?Funder {

????address?addr;

????uint?amount;

? }

??struct?Campaign {

????address?beneficiary;

????uint?fundingGoal;

????uint?numFunders;

????uint?amount;

????mapping?(uint?=>?Funder) funders;

? }

??uint?numCampaigns;

??mapping?(uint?=>?Campaign) campaigns;

??function?newCampaign(address?beneficiary,?uint?goal)?returns?(uint?campaignID) {

??? campaignID?=?numCampaigns++;?// campaignID is return variable??campaignID是返回的變量

????// Creates new struct and saves in storage. We leave out the mapping type.?創(chuàng)建一個新的結(jié)構(gòu)體,保存在存儲器里, 保留了映射類型

??? campaigns[campaignID]?=?Campaign(beneficiary, goal, 0, 0);

? }

??function?contribute(uint?campaignID) {

??? Campaign c?=?campaigns[campaignID];

????????// Creates a new temporary memory struct, initialised with the given values?創(chuàng)建了一個新的臨時內(nèi)存結(jié)構(gòu)體,用給定的值進(jìn)行初始化

????????// and copies it over to storage.?拷貝到存儲器上

????????// Note that you can also use Funder(msg.sender, msg.value) to initialise.?注意你可以使用 Funder(msg.sender, msg.value)來初始化

??? c.funders[c.numFunders++]?=?Funder({addr:?msg.sender, amount:?msg.value});

??? c.amount?+=?msg.value;

? }

??function?checkGoalReached(uint?campaignID)?returns?(bool?reached) {

??? Campaign c?=?campaigns[campaignID];

????if?(c.amount?<?c.fundingGoal)

??????return?false;

??? c.beneficiary.send(c.amount);

??? c.amount?=?0;

????return?true;

? }}

此(例子)合約沒有提供眾籌合約的完整功能,? 但它包含了必要的基本概念,以便(讓我們更好地)理解結(jié)構(gòu)體。結(jié)構(gòu)體類型可以是內(nèi)部映射或者是數(shù)組,他們本身也可以包含映射和數(shù)組。

通常這是不可能,即一個結(jié)構(gòu)體包含一個自身類型的成員, 雖然結(jié)構(gòu)體本身可以是一個映射的值類型成員。這個限制是必要的, 原因是結(jié)構(gòu)體的大小是有限的。

注意所有的函數(shù)中, 結(jié)構(gòu)類型是賦值給一個局部變量(默認(rèn)存儲數(shù)據(jù)的位置)。這并不復(fù)制結(jié)構(gòu)體,僅僅保存了一個引用, 本地變量的賦值最終還是以寫進(jìn)了狀態(tài)中。

當(dāng)然,您也可以直接訪問結(jié)構(gòu)體的成員變量,而不用賦值到一個局部變量,如campaigns[campaignID].amount = 0.

映射

映射類型被聲明為 mapping _KeyType => _ValueType,? _KeyType可以是除了映射以外的其他任何類型,_ValueType可以是任何類型,包括映射。

映射可以被視為初始化的散列表,這樣每一個鍵值都存在, 這些鍵值在字節(jié)表示上是全零。相似性到此為止,盡管:key數(shù)據(jù)實際上并不是存儲在一個映射中,它只有在使用sha3哈希查找值使用。

因此,映射沒有長度,也沒有一個鍵或值的被“set”的概念。

映射是只允許為狀態(tài)變量(在內(nèi)部函數(shù)中作為一個存儲引用類型)。

包括左值操作的操作符

如果是一個左值操作(即一個可以賦值給它的變量),可以使用以下的操作符:

a += e相當(dāng)于 a = a + e。操作符- = * =,/ = % = | = & = ^ = 都有相應(yīng)的定義。a++和a--相當(dāng)于a+ = 1 /a - = 1,但是表達(dá)式本身還有一個操作前的值。相比之下, --a和++a有相同的影響但返回值改變。

刪除

刪除一個指定類型的初始值為整數(shù),即相當(dāng)于a= 0,但是它也可以用于數(shù)組,它分配一個動態(tài)數(shù)組的長度為零或一個靜態(tài)數(shù)組長度相同的所有元素重置。對于結(jié)構(gòu)體,它分配一個struct,重置所有成員。

刪除沒有影響整體映射(如映射的鍵可能是任意的,通常是未知的)。如果你刪除一個結(jié)構(gòu),它將重置沒有映射的所有成員,也可以是遞歸的成員,除非它們映射。然而,個別鍵和他們的映射是可以刪除。

重要的是要注意,刪除一個a的賦值,? 即它存儲在一個新的對象。

contract?DeleteExample {

??uint?data;

??uint[] dataArray;

??function?f() {

????uint?x?=?data;

????delete?x;?// sets x to 0, does not affect data

????delete?data;?// sets data to 0, does not affect x which still holds a copy

????uint[] y?=?dataArray;

????delete?dataArray;?// this sets dataArray.length to zero, but as uint[] is a complex object, also

????// y is affected which is an alias to the storage object

????// On the other hand: "delete y" is not valid, as assignments to local variables

????// referencing storage objects can only be made from existing storage objects.

? }}

contract?DeleteExample {

??uint?data;

??uint[] dataArray;

??function?f() {

????uint?x?=?data;

????delete?x;?// sets x to 0, does not affect data? 設(shè)置x為0, 不影響data

????delete?data;?// sets data to 0, does not affect x which still holds a copy? 設(shè)置data為0,x不受影響,x仍然有一個拷貝

????uint[] y?=?dataArray;

????delete?dataArray;?// this sets dataArray.length to zero, but as uint[] is a complex object, also?dataArray.length長度是0。但是uint[ ]是一個復(fù)雜對象, y受影響,其是存儲對象的別名

????// y is affected which is an alias to the storage object

????// On the other hand: "delete y" is not valid, as assignments to local variables?另外, "delete y"是非法的,因為y是賦值到本地變量

????// referencing storage objects can only be made from existing storage objects.引用存儲對象僅僅來自于現(xiàn)有的存儲對象

? }}

基本類型之間的轉(zhuǎn)換

隱式轉(zhuǎn)換

如果一個操作符應(yīng)用于不同類型,? 編譯器(就會)試圖隱式把操作數(shù)的類型,從一種類型轉(zhuǎn)換到其他類型(賦值也是如此)。一般來說,一個隱式的值類型之間的轉(zhuǎn)換是可能的,如果是語義敏感的話,信息不會丟失:unt8可轉(zhuǎn)換成uint16, int128, int256,? 但int8不能轉(zhuǎn)換成uint256(因為uint256放不下? 如 -1)。此外,無符號整數(shù)可以轉(zhuǎn)換成相同或更大的尺寸的bytes ,? 但反過來,不行 。任何類型都可以轉(zhuǎn)化為uint160,也可以轉(zhuǎn)換為地址。

顯式轉(zhuǎn)換

如果編譯器不允許隱式轉(zhuǎn)換,但你知道你在做什么,一個顯式的類型轉(zhuǎn)換有時是可能的:

int8 y = 3;

uint x =uint(y);

這個代碼片段結(jié)尾 , x的值是 0xfffff . .fd(64個十六進(jìn)制字符),-3在256位的二進(jìn)制補碼表示。

如果一個類型是顯式地轉(zhuǎn)換為一個更小的類型,高階位將被移除。

uint32 = 0x12345678;

uint16 b = uint16(a);/ /?*b will be 0x5678 now*??*b現(xiàn)在變成了0x5678,(少了1234)*

類型推導(dǎo)

為方便起見,它并不總是必須顯式地指定一個變量的類型,編譯器會自動從第一個賦值表達(dá)式的變量類型里推斷出新變量的類型:

uint20 x = 0 x123;

var y = x;

在這里,y的類型是uint20。在函數(shù)參數(shù)或返回參數(shù)是不可能使用var(這個關(guān)鍵字)的。

警告

這個類型僅僅是從第一次賦值推導(dǎo)得出的,所以以下代碼片段的循環(huán)是無限的,? 因為 i 的類型是uint8, 這種類型的任何值都小于2000。for (var i = 0;< 2000;i+ +){…}

Next??Previous

? Copyright 2015, Ethereum. Revision 9b9d10b4.

Built with?Sphinx?using a?theme?provided by?Read the Docs.

?Read the Docsv: latest?

上一篇:編程規(guī)范下一篇:常見問題