solidity基礎(chǔ)(2)

  1. solidity的數(shù)據(jù)位置特性深入了解
    • 簡(jiǎn)介:
      代碼在執(zhí)行前哨毁,一般會(huì)編譯成指令妹懒。指令就是一個(gè)個(gè)邏輯知染,邏輯操作的是數(shù)據(jù)。代碼或者說(shuō)業(yè)務(wù)羞秤,操作的其實(shí)都是數(shù)據(jù)。非區(qū)塊鏈中左敌,代碼操作的數(shù)據(jù)瘾蛋,一般會(huì)存到數(shù)據(jù)庫(kù)中。
      在區(qū)塊鏈中矫限,區(qū)塊鏈本身就是一個(gè)數(shù)據(jù)庫(kù)哺哼。如果使用區(qū)塊鏈標(biāo)記物產(chǎn)的所有權(quán),歸屬信息將會(huì)被記錄到區(qū)塊上叼风,所有人都無(wú)法篡改取董,以標(biāo)明不可爭(zhēng)議的擁有權(quán)。所以在區(qū)塊鏈的編程中无宿,有一個(gè)數(shù)據(jù)位置的屬性用來(lái)標(biāo)識(shí)變量是否需要持久化到區(qū)塊鏈上茵汰。
    • 數(shù)據(jù)位置的類(lèi)型
      • 數(shù)據(jù)位置:變量的存儲(chǔ)位置屬性,有三種類(lèi)型,memory,storage,calldata
        • memory:儲(chǔ)存位置和我們普通程序的內(nèi)存類(lèi)似孽鸡,即分配蹂午,即使用栏豺,越過(guò)作用域即不可被訪問(wèn),等待被回收
        • storage:數(shù)據(jù)將永久存在于區(qū)塊鏈上
        • calldata:一般只有外部函數(shù)的參數(shù)(不包括返回參數(shù))被強(qiáng)制指定為calldata豆胸,這種數(shù)據(jù)位置是只讀的奥洼,不會(huì)持久到區(qū)塊鏈上
    • 默認(rèn)數(shù)據(jù)位置
      1. 參數(shù):
        默認(rèn)的函數(shù)參數(shù),包括返回的參數(shù)配乱,是memory

         pragma solidity ^0.4.18;
         contract FunctionTest {
           function test(uint a) view returns(uint r) {
             //這里的a和r都是memory
             r = a;
           }
         }
        
      2. 局部變量和狀態(tài)變量
        狀態(tài)變量和局部變量溉卓,是storage;定義在函數(shù)外部的是狀態(tài)變量,定義在函數(shù)內(nèi)部的是局部變量

         pragma solidity ^0.4.18;
         contract FunctionTest {
           struct S{string a;uint b;}
           //狀態(tài)變量搬泥,默認(rèn)是storage
           S s;
           function test(S s) private {
             //局部變量桑寨,默認(rèn)是storage
             S tmp;
           }
         }
        
    • 數(shù)據(jù)位置間相互轉(zhuǎn)換
      1. storage轉(zhuǎn)換為storage
        當(dāng)我們把一個(gè)storage類(lèi)型的變量賦值給另一個(gè)storage時(shí),我們只是修改了它的指針

           pragma solidity ^0.4.18;
           contract Test {
             struct S{string s;uint n;}
             S s;
             function fTest(S storage t) internal {
               s = t;//此時(shí),s的指針與t相同
               t.s = "123";//修改t就當(dāng)于修改s
             }
             function b() public view returns(string) {
               s = S("456",0);
               fTest(s);
               return s.s;
               //返回值是"123"
             }
           }
        
      2. memory轉(zhuǎn)換為storage

        • memory賦值給狀態(tài)變量
          將一個(gè)memory類(lèi)型的變量賦值給一個(gè)狀態(tài)變量時(shí)忿檩,實(shí)際是將內(nèi)存變量拷貝到存儲(chǔ)中

           pragma solidty 0.4.18;
           contract Test {
             struct S{string a;uint b;}
             S s;
             function fTest(S memory a) internal {
               s = a;//只是把a(bǔ)的值賦給s
               a.a = "123";//修改a并不能對(duì)s造成修改
             }
             function b() public view returns(string) {
               functionTest(S("456",0));
               return s.s;
               //返回值任然是"456"
             }
           }
          

          由此尉尾,我們發(fā)現(xiàn),在“memory與狀態(tài)變量”的賦值中燥透,他們只是值拷貝沙咏,后續(xù)他們不再有任何的關(guān)系

        • memory賦值給局部變量
          由于在區(qū)塊鏈中,storage必須是靜態(tài)分配存儲(chǔ)空間的班套,局部變量雖然是一個(gè)storage的肢藐,但它僅僅是一個(gè)storage類(lèi)型的指針,所以進(jìn)行這樣的賦值吱韭,實(shí)際會(huì)產(chǎn)生錯(cuò)誤吆豹,當(dāng)然我們可以通過(guò)修改參數(shù)或局部變量的類(lèi)型來(lái)解決這個(gè)問(wèn)題

           //將參數(shù)的數(shù)據(jù)位置變?yōu)閟torage
           function fTest(S storage t) internal {
             S tmp = t;
           }
           function b(S t) internal {
             //將局部變量的數(shù)據(jù)位置變?yōu)閙emory
             S memory tmp = t;
           }
          
      3. storage轉(zhuǎn)為memory
        storage轉(zhuǎn)為memory,實(shí)際是將數(shù)據(jù)從storage拷貝到memory中理盆,和把memory轉(zhuǎn)為狀態(tài)變量的例子一樣痘煤,我們可以歸納為,他們之間的轉(zhuǎn)換猿规,對(duì)memory的修改并不會(huì)在storage上生效衷快,他們之間只是單純的數(shù)據(jù)拷貝

      4. memory轉(zhuǎn)為memory
        memory之間是引用傳遞,并不會(huì)拷貝數(shù)據(jù)姨俩,即在函數(shù)內(nèi)部對(duì)memory的修改蘸拔,在函數(shù)外依然生效。

    • 參考資料:
      官方文檔
      什么是值傳遞环葵,引用傳遞都伪,指針傳遞

  2. solidity的數(shù)據(jù)位置特性深入了解
    在solidity中,支持編譯定長(zhǎng)數(shù)組和變長(zhǎng)數(shù)組积担;如,一個(gè)類(lèi)型為T(mén)猬仁,長(zhǎng)度為k的數(shù)組帝璧,可以聲明為T[k]先誉,類(lèi)型為T(mén)的變長(zhǎng)數(shù)組則聲明為T[]
    • 創(chuàng)建一個(gè)數(shù)組

      1. 通過(guò)字面量創(chuàng)建定長(zhǎng)數(shù)組

        • 字面量
        • 元素類(lèi)型是剛好能存儲(chǔ)的元素類(lèi)型,例如[1,2,3]的烁,只需uint8便可存儲(chǔ)褐耳,所以元素類(lèi)型是uint8類(lèi)型,而假設(shè)我們聲明的類(lèi)型不是uint8,那么元素類(lèi)型必須通過(guò)顯示的類(lèi)型轉(zhuǎn)換渴庆,如:uint[3] memory a = [uint(1),2,3];
        • 另外铃芦,字面量方式聲明的數(shù)組是定長(zhǎng)的,且實(shí)際長(zhǎng)度要與聲明的長(zhǎng)度相匹配襟雷,否則編譯器會(huì)報(bào)錯(cuò)
      2. new關(guān)鍵字
        對(duì)于變長(zhǎng)數(shù)組刃滓,在初始化分配空間前不可使用,可以通過(guò)new關(guān)鍵字來(lái)初始化一個(gè)數(shù)組,之后才可以賦值使用耸弄;
        不能用new來(lái)初始話storage的局部變量咧虎,會(huì)報(bào)錯(cuò)

         pragma solidity ^0.4.18;
         contract NewArray {
           uint[] stateVar;
           function f() {
             //定義一個(gè)變長(zhǎng)數(shù)組
             uint[] memory memVar;
             //不能在使用new初始化以前使用,編譯后會(huì)報(bào)錯(cuò)
             //VM Exception: invalid opcode
             //memVar [0] = 100;
             //通過(guò)new來(lái)初始化變長(zhǎng)數(shù)組
             memVar = new uint[](2);
             stateVar = new uint[](2);
             stateVar[0] = 1;
             memVar[0] = 1;
           }
         }
        
    • 數(shù)據(jù)的屬性和方法

      1. length屬性
        數(shù)組有一個(gè)length屬性计呈,對(duì)于storage的變長(zhǎng)數(shù)組砰诵,可以通過(guò)給length賦值來(lái)調(diào)整數(shù)組長(zhǎng)度

        • storage
          數(shù)據(jù)位置為storage的變長(zhǎng)數(shù)組,可以通過(guò)length來(lái)不斷的修改長(zhǎng)度;
          還可以通過(guò)push()方法捌显,來(lái)隱式的調(diào)整數(shù)組長(zhǎng)度;
          不能通過(guò)對(duì)超出當(dāng)前數(shù)組的長(zhǎng)度序號(hào)元素賦值的方式茁彭,來(lái)實(shí)現(xiàn)數(shù)組長(zhǎng)度的自動(dòng)擴(kuò)展
        • memory
          對(duì)于memory的變長(zhǎng)數(shù)組,不支持修改length屬性扶歪,來(lái)調(diào)整數(shù)組大欣矸巍;memory的變長(zhǎng)數(shù)組雖然可以通過(guò)參數(shù)靈活指定大小击罪,但一旦創(chuàng)建哲嘲,大小不可調(diào)整。
      2. push方法
        變長(zhǎng)的storage數(shù)組和bytes(不包括string)有一個(gè)push()方法媳禁,可以將一個(gè)新元素附加到數(shù)組末端眠副,返回值為當(dāng)前長(zhǎng)度
        push()方法不能用于定長(zhǎng)數(shù)組和memory數(shù)組

         pragma solidity  ^0.4.18;
         contract Test {
           uint[] a;
           function fTest() public returns(uint[],uint) {
             a.push(1);
             a.push(2);
             //初始化,之前push的值被被初始化為0
             //同時(shí)長(zhǎng)度變?yōu)槌跏蓟o定的值
             a = new uint[](1);
             //初始化之后仍然可以使用push()擴(kuò)容
             a.push(3);
             return (a.a.length);
           }
        
           function b() public returns(uint[]) {
             uint[] memory c;
             //c.push(1)  error
           }
         }
        
      3. 下標(biāo)
        與大多數(shù)語(yǔ)言一樣竣稽,數(shù)組可以通過(guò)數(shù)字下標(biāo)訪問(wèn)囱怕,從0開(kāi)始
        如果狀態(tài)變量的類(lèi)型為數(shù)組,也可以標(biāo)記為public毫别,從而讓solidity創(chuàng)建一個(gè)訪問(wèn)器

         pragma solidity ^0.4.18;
         contract Test {
           uint[] public a = [uint(1)];
         }
        

        如上面的合約在Remix運(yùn)行后娃弓,需要我們填入下標(biāo)數(shù)字來(lái)訪問(wèn)具體某個(gè)元素

    • 多維數(shù)組
      多維數(shù)組的定義與非區(qū)塊鏈語(yǔ)言類(lèi)似。如岛宦,我們要?jiǎng)?chuàng)建一個(gè)長(zhǎng)度為5uint數(shù)組台丛,每個(gè)元素又是一個(gè)變長(zhǎng)數(shù)組。將被聲明為uint[][5](<font color=red>注意:定義方式對(duì)比大多語(yǔ)言來(lái)說(shuō)是反的,使用下標(biāo)訪問(wèn)元素時(shí)與其他語(yǔ)言一致</font>)

       pragma solidity ^0.4.18;
       contract Test {
         //聲明一變長(zhǎng)數(shù)組挽霉,里面的每一個(gè)元素是3長(zhǎng)度的定長(zhǎng)數(shù)組
         uint[3][] flags;
         function fTest() public returns(uint) {
           return flags.push([uint(1),2,3]);
         }
      
         function getValue() public returns(uint) {
           return flags[0][2];
           //結(jié)果為3
         }
       }
      
    • bytes與string
      bytesstring是一種特殊的數(shù)組防嗡,bytes類(lèi)似byte[],但在外部函數(shù)作為參數(shù)調(diào)用中侠坎,會(huì)進(jìn)行壓縮打包蚁趁,更省空間,所以應(yīng)該盡量使用bytes实胸,string類(lèi)似bytes他嫡,但不提供長(zhǎng)度和按序號(hào)的訪問(wèn)方式
      由于bytesstring,可以自由轉(zhuǎn)換庐完,例如钢属,可以將字符串s通過(guò)bytes(s)轉(zhuǎn)換為一個(gè)bytes,但是需要注意的是假褪,通過(guò)這種方式訪問(wèn)到的是UTF-8編碼的碼流署咽,并不是獨(dú)立的一個(gè)個(gè)字符。比如中文編碼是多字節(jié)生音,變長(zhǎng)的宁否,所以訪問(wèn)到的很有可能只是其中的一個(gè)代碼點(diǎn)。
      同時(shí)缀遍,bytes和變長(zhǎng)的storage數(shù)組一樣慕匠,也支持push()

    • 限制
      在外部函數(shù)中,不能使用多維數(shù)組域醇,另外台谊,因?yàn)镋VM的限制,不能通過(guò)外部函數(shù)返回變長(zhǎng)的數(shù)據(jù)

       pragma solidity ^0.4.18;
       contract ArrayWarning {
         function f() returns(uint[]) {
           return new uint[](1);
         }
         /*function g() returns(uint[]) {
           return this.f();
         }*/
       }
      

      f()返回的是uint[]的變長(zhǎng)數(shù)組譬挚,使用web3.js的方式可以訪問(wèn)锅铅,但是用solidity的外部函數(shù)的訪問(wèn)方式,將不能編譯通過(guò)
      對(duì)于這樣的問(wèn)題的一種臨時(shí)解決方法减宣,是使用一個(gè)非常大的定長(zhǎng)數(shù)組

    • 參考資料-padding問(wèn)題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盐须,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子漆腌,更是在濱河造成了極大的恐慌贼邓,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闷尿,死亡現(xiàn)場(chǎng)離奇詭異塑径,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)填具,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)统舀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事绑咱〈律福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵描融,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衡蚂,道長(zhǎng)窿克,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任毛甲,我火速辦了婚禮年叮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玻募。我一直安慰自己只损,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布七咧。 她就那樣靜靜地躺著跃惫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪艾栋。 梳的紋絲不亂的頭發(fā)上爆存,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蝗砾,去河邊找鬼先较。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悼粮,可吹牛的內(nèi)容都是我干的闲勺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扣猫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菜循!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起苞笨,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤债朵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后瀑凝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體序芦,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年粤咪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谚中。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宪塔,靈堂內(nèi)的尸體忽然破棺而出磁奖,到底是詐尸還是另有隱情,我是刑警寧澤某筐,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布比搭,位于F島的核電站,受9級(jí)特大地震影響南誊,放射性物質(zhì)發(fā)生泄漏身诺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一抄囚、第九天 我趴在偏房一處隱蔽的房頂上張望霉赡。 院中可真熱鬧,春花似錦幔托、人聲如沸穴亏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗓化。三九已至,卻和暖如春攒驰,著一層夾襖步出監(jiān)牢的瞬間蟆湖,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工玻粪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隅津,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓劲室,卻偏偏與公主長(zhǎng)得像伦仍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子很洋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容