-
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ù)位置
-
參數(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; } }
-
局部變量和狀態(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)換
-
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" } }
-
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; }
-
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ù)拷貝memory
轉(zhuǎn)為memory
memory
之間是引用傳遞,并不會(huì)拷貝數(shù)據(jù)姨俩,即在函數(shù)內(nèi)部對(duì)memory
的修改蘸拔,在函數(shù)外依然生效。
-
- 參考資料:
官方文檔
什么是值傳遞环葵,引用傳遞都伪,指針傳遞
- 簡(jiǎn)介:
-
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ù)組
-
通過(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ò)
-
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ù)的屬性和方法
-
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)整。
- storage
-
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 } }
-
下標(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)度為5
的uint
數(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
bytes
與string
是一種特殊的數(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)方式
由于bytes
與string
,可以自由轉(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ù)組
-
solidity基礎(chǔ)(2)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門(mén)统舀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事绑咱〈律福” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵描融,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衡蚂,道長(zhǎng)窿克,這世上最難降的妖魔是什么? 我笑而不...
- 正文 為了忘掉前任毛甲,我火速辦了婚禮年叮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玻募。我一直安慰自己只损,他們只是感情好,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布七咧。 她就那樣靜靜地躺著跃惫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪艾栋。 梳的紋絲不亂的頭發(fā)上爆存,一...
- 那天,我揣著相機(jī)與錄音蝗砾,去河邊找鬼先较。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悼粮,可吹牛的內(nèi)容都是我干的闲勺。 我是一名探鬼主播,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼扣猫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菜循!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起苞笨,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤债朵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后瀑凝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體序芦,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年粤咪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谚中。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
- 正文 年R本政府宣布比搭,位于F島的核電站,受9級(jí)特大地震影響南誊,放射性物質(zhì)發(fā)生泄漏身诺。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒙蒙 一抄囚、第九天 我趴在偏房一處隱蔽的房頂上張望霉赡。 院中可真熱鬧,春花似錦幔托、人聲如沸穴亏。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗓化。三九已至,卻和暖如春攒驰,著一層夾襖步出監(jiān)牢的瞬間蟆湖,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓劲室,卻偏偏與公主長(zhǎng)得像伦仍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子很洋,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 1. 合約A中引用合約B充蓝,是根據(jù) import和路徑 引用。一旦合約A編譯完成喉磁,那么意味著合約B此時(shí)此刻的abi...
- 1.編輯器說(shuō)明 (1)推薦編輯器目前嘗試 Solidity 編程的最好的方式是使用 Remix (需要時(shí)間加載谓苟,請(qǐng)...
- 序言本文是 Solidity 文檔(以太坊官方 Solidity 開(kāi)發(fā)手冊(cè))中文版連載的第五部分。這個(gè)連載的前四部...
- 為什么有些人投資可以做到年化收益率20%,有些人卻在股市沉浮中原地踏步孕暇? 為什么有些人買(mǎi)的基金持續(xù)賺錢(qián)仑撞,而你買(mǎi)的基...
- 阿耐是我非常喜歡的商業(yè)小說(shuō)作家,她最為出名的《大江東去》我不止一次地在平臺(tái)上跟朋友推薦.不過(guò)有趣的是沮翔,讓大多數(shù)我朋...