您好,登錄后才能下訂單哦!
本篇內容介紹了“solidity表達式和控制結構怎么使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
除了 switch和goto,solidity的絕大多數控制結構均來自于C / JavaScript,if, else, while, for, break, continue, return, ? :, 的語義均和C / JavaScript一樣。
條件語句中的括號不能省略,但在單條語句前后的花括號可以省略。
注意,(Solidity中 )沒有象C和JavaScrip那樣 ,從非布爾類型類型到布爾類型的轉換, 所以if (1){…}不是合法的Solidity(語句)。
內部函數調用
當前合約和函數可以直接調用(“內部”),也可以遞歸, 所以你會看到在這個“荒謬”的例子:
contract c { function g(uint a) returns (uint ret) { return f(); } function f() returns (uint ret) { return g(7) + f(); }}
這些函數調用在EMV里翻譯成簡單的jumps 語句。當前內存沒有被清除, 即通過內存引用的函數是非常高效的。僅僅同一個合約的函數可在內部被調用。
外部函數調用
表達式this.g(8);也是一個合法的函數調用, 但是這一次,這個函數將被稱為“外部”的, 通過消息調用,而不是直接通過jumps調用。其他合約的函數也是外部調用。對于外部調用,所有函數參數必須被復制到內存中。
當調用其他合約的函數時, 這個調用的wei的數量被發送和gas被定義:
contract InfoFeed { function info() returns (uint ret) { return 42; } } contract Consumer { InfoFeed feed; function setFeed(address addr) { feed = InfoFeed(addr); } function callFeed() { feed.info.value(10).gas(800)(); } }
注意:表達式InfoFeed(addr)執行顯式的類型轉換, 意思是“我們知道給定的地址的合約類型是InfoFeed”, 這并不執行構造函數。 我們也可以直接使用函數setFeed(InfoFeed _feed) { feed = _feed; }。 注意: feed.info.value(10).gas(800)是(本地)設置值和函數調用發送的gas數量, 只有最后的括號結束后才完成實際的調用。
有參數的函數調用可以有名字,不使用參數的名字(特別是返回參數)可以省略。
contract c { function f(uint key, uint value) { ... } function g() { // named arguments 具名參數 f({value: 2, key: 3}); } // omitted parameters 省略名字的參數 function func(uint k, uint) returns(uint) { return k; } }
表達式的計算順序是不確定的(準確地說是, 順序表達式樹中的子節點表達式計算順序是不確定的的, 但他們對節點本身,計算表達式順序當然是確定的)。只保證語句執行順序,以及布爾表達式的短路規則。
析構賦值并返回多個值
Solidity內部允許元組類型,即一系列的不同類型的對象的大小在編譯時是一個常量。這些元組可以用來同時返回多個值,并且同時將它們分配給多個變量(或左值運算)
contract C { uint[] data; function f() returns (uint, bool, uint) { return (7, true, 2); } function g() { // Declares and assigns the variables. Specifying the type explicitly is not possible. var (x, b, y) = f(); // Assigns to a pre-existing variable. (x, y) = (2, 7); // Common trick to swap values -- does not work for non-value storage types. (x, y) = (y, x); // Components can be left out (also for variable declarations). // If the tuple ends in an empty component, // the rest of the values are discarded. (data.length,) = f(); // Sets the length to 7 // The same can be done on the left side. (,data[3]) = f(); // Sets data[3] to 2 // Components can only be left out at the left-hand-side of assignments, with // one exception: (x,) = (1,); // (1,) is the only way to specify a 1-component tuple, because (1) is // equivalent to 1. } } contract C { uint[] data; function f() returns (uint, bool, uint) { return (7, true, 2); } function g() { // Declares and assigns the variables. Specifying the type explicitly is not possible. 聲明和賦值變量,不必顯示定義類型 var (x, b, y) = f(); // Assigns to a pre-existing variable. 賦值給已經存在的變量 (x, y) = (2, 7); // Common trick to swap values -- does not work for non-value storage types. 交換值的技巧-對非值存儲類型不起作用 (x, y) = (y, x); // Components can be left out (also for variable declarations). 元素可排除(對變量聲明也適用) // If the tuple ends in an empty component, 如果元組是以空元素為結尾 // the rest of the values are discarded. 值的其余部分被丟棄 (data.length,) = f(); // Sets the length to 7 設定長度為7 // The same can be done on the left side. 同樣可以在左側做 (,data[3]) = f(); // Sets data[3] to 2 將data[3] 設為2 // Components can only be left out at the left-hand-side of assignments, with // one exception: 組件只能在賦值的左邊被排除,有一個例外 (x,) = (1,); // (1,) is the only way to specify a 1-component tuple, because (1) is (1,)是定義一個元素的元組,(1)是等于1 // equivalent to 1. }}
對于象數組和結構體這樣的非值類型,賦值的語義更復雜些。賦值到一個狀態變量總是需要創建一個獨立的副本。另一方面,對基本類型來說,賦值到一個局部變量需要創建一個獨立的副本, 即32字節的靜態類型。如果結構體或數組(包括字節和字符串)從狀態變量被賦值到一個局部變量, 局部變量則保存原始狀態變量的引用。第二次賦值到局部變量不修改狀態,只改變引用。賦值到局部變量的成員(或元素)將改變狀態。
有一些自動拋出異常的情況(見下文)。您可以使用throw 指令手動拋出一個異常。異常的影響是當前執行的調用被停止和恢復(即所有狀態和余額的變化均沒有發生)。另外, 異常也可以通過Solidity 函數 “冒出來”, (一旦“異常”發生, 就send "exceptions", call和callcode底層函數就返回false)。
捕獲異常是不可能的。
在接下來的例子中,我們將演示如何輕松恢復一個Ether轉移,以及如何檢查send的返回值:
contract Sharer { function sendHalf(address addr) returns (uint balance) { if (!addr.send(msg.value/2)) throw; // also reverts the transfer to Sharer return this.balance; } } contract Sharer { function sendHalf(address addr) returns (uint balance) { if (!addr.send(msg.value/2)) throw; // also reverts the transfer to Sharer 也恢復Sharer的轉移 return this.balance; } }
目前,Solidity異常自動發生,有三種情況, :
如果你訪問數組超出其長度 (即x[i] where i >= x.length)
如果一個通過消息調用的函數沒有正確的執行結束(即gas用完,或本身拋出異常)。
如果一個庫里不存在的函數被調用,或Ether被發送到一個函數庫里。
在內部,當拋出異常時 ,Solidity就執行“非法jump”, 從而導致EMV(Ether虛擬機)恢復所有更改狀態。這個原因是沒有安全的方法可以繼續執行, 預期的結果沒有發生。由于我們想保留事務的原子性,(所以)最安全的做法是恢復所有更改,并使整個事務(或者至少調用)沒有受影響。
“solidity表達式和控制結構怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。