Solidity

為什麼沒有返回 x(function setArr)?

  • July 29, 2020
pragma solidity >=0.5.0 <0.7.0;
contract Example{
   uint256[3] x;
   function setArr(uint256[3] memory y) public returns(uint256[3] memory){
       x=y;
      return getArr(x);
   }
   function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory)
   {  return z;
   }
}

簡短的回答:

按照設計,沒有語法可以做到這一點。

長答案:

它的“為什麼”與具有與 CPU 不同的約束的 EVM 有關。

uint256[3] storage z是一個storage指針。這意味著它由一個指向邏輯槽的 32 字節指針表示,其餘的儲存佈局是隱式的。這也意味著該功能無法從合約外部訪問。外部的任何東西都不能被信任直接引用儲存位置。

uint256[3] memory是一個memory變數。這些是暫時的,並且在函式執行後它們不會持續存在。這暗示了他們生活在其他地方的基本事實。它們在記憶體空間中,而不是儲存空間中。

所以……從儲存到記憶體意味著複製數據。由於(至少)兩個原因,它不會自動完成。

  1. 太多的巫術會阻礙有效契約的設計。這裡的慣用方法,或者如果有明顯多於三個的循環,則可以使開發人員清楚地知道工作正在發生。閱讀、複製和寫作。

你可以:

function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory x) {  
 x[0]=z[0];
 x[1]=z[1];
 x[2]=z[2];
}

這很清楚。

for(uint i=0; i<3; i++) { ...也會這樣做,但由於需要更新和檢查i's狀態以及跳轉,因此成本更高。這導致了第二個原因,即 IMO 更為根本。

  1. 像這樣的過程具有 O(n) 複雜度,這意味著計算成本與數組的長度成正比。無界循環是一個陷阱,它可以使合約看起來有效,然後大規模失敗。當計算能力基本上是無限的,但在對可用計算資源有硬性限制的情況下,迭代和遞歸是強大的工具。這導致人們重新考慮契約該做什麼。https://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad

如果編譯器有高級語法來幫助將意圖轉換為 OPCODE,那麼這個問題就不會消失。EVN 中的所有內容對於固定的工作單元都有固定的成本,這一原則在高級語言中也很明顯。換句話說,如果有一個顯式或隱式的“複製數組”函式,那將是非常危險的。

希望能幫助到你。

引用自:https://ethereum.stackexchange.com/questions/85364