1.Solidity基礎
友情提示:每一句話都非常重要,每一個點都是細節,再者本教程適合有一定編程基礎的小伙伴快速入門
基本語法,整數溢位以及例外處理,位元組陣列,動態位元組陣列,字串,字串與位元組陣列的相互轉換,幫助大家快速入門Solidity
這里直接給一段代碼
pragma solidity ^0.4.16;
contract Helloworld {
string Myname = "張三";
function getName() public view returns(string) {
return Myname;
}
function setName(string newname) public {
Myname = newname;
}
function pureTest(string _name) public pure returns (string) {
return _name;
}
}
這里使用的編輯器是remix網頁編輯器:點擊進入remix編輯器
下面我們對這段代碼進行分析
在java中,已經有很多的小我們大致了解,所以我們學習solidity只需要學習它與其他語言不同的地方
-
第一行的prama,是solidity的編譯控制指令,那我們這行代碼的意思是,源檔案不允許被0.4.16以下,以及大于等于0.5.0版本的編譯器所編譯,簡單來說,允許的范圍就是左閉右開
0.4.16<=編譯器版本<0.5.0
在此區間的編譯器版本是可以編譯的,
-
contract關鍵字,相當于java中的class,定義一個合約
-
view關鍵字,這個是Solidity特有的關鍵字,因為solidity最終是用在合約上,所以會有相關的功能,而view就是這些功能的其中一個,view只能用來修飾方法,而被修飾的方法不能修改狀態變數,也就是在java中的類的屬性,在這里這個狀態變數就是Myname,在這里我們可以看到getName()方法并沒有修改Myname的值
-
運行這個代碼,我們先呼叫getName函式,結果如下
這張圖片顯示運行結果,運行成功

這張圖片顯示油費消耗,記住這個數字 -
運行setName()方法,這個方法需要傳入一個引數,我們在這里傳入"李四",點擊運行,之后再運行getName()重新獲取值,結果如下


但是我們發現油費改變了,這說明了什么? -
當我們繼續點擊getName()運行多次的時候,油費依舊不變,而當我們再次運行setName()方法的時候油費又會改變,
-
這說明了被view修飾的方法不會消耗油費,因為它不需要改變狀態變數,所以view關鍵字還有節約油費的作用
-
pure關鍵字,被這個關鍵字修飾的方法不允許訪問狀態變數,所以也不需要花費油費,
-
bool,&& ,||,用法與java中完全一致,在這里不過多解釋,
-
uint關鍵字,代表非負整型,默認是uint256,256是指256個位元位,
8bit=1byte
- solidity中也支持方法多載
- 位運算子:由于solidity是用來部署合約,所以對記憶體要求很高,為了節約記憶體,位運算子顯得相當重要
&:按位與,同時為1,得到1,有一個及以上為0,就是0
|:按位或,同時為0,得到0,有一個及以上為1,就是1
~:取反,0變成1,1變成0(只需要一串數字就可以)
^:按位異或,相同為0,不相同為1
<<:左移
.>>:右移
將上面的符號全部測驗一遍,這里不給出結果,有興趣的可以自己去運行一下
pragma solidity ^0.4.16;
contract BoolTest {
uint8 a = 4;
uint8 b = 2;
function plus() public view returns(uint8){
return a + b;
}
function minus() public view returns(uint8){
return a - b;
}
function multiply() public view returns(uint8){
return a * b;
}
function divide() public view returns(uint8){
return a / b;
}
function power() public view returns(uint8){
return a ** b;
}
function test1() public view returns(uint8){
return a&b;
}
function test2() public view returns(uint8){
return a|b;
}
function test3() public view returns(uint8){
return ~b;
}
function test4() public view returns(uint8){
return a^b;
}
function test5() public view returns(uint8){
return a<<1;
}
function test6() public view returns(uint8){
return a>>1;
}
}
2.整數溢位以及例外處理
- 接下來我們要介紹非常危險的整數溢位問題,附上代碼,
function flow() public pure returns(uint8){
uint8 mm = 255;
return mm;
}
我們知道,8個位元位的資料范圍是0~255,所以這個方法會回傳一個mm的值,是255,運行結果沒問題,
接下來我們修改一下代碼,修改后的代碼在下方
function flow() public pure returns(uint8){
uint8 mm = 255;
mm++;
return mm;
}
代碼修改后,mm理應變成256,但是256已結超過了8個位元位的取值范圍,所以會出現錯誤,運行結果:

可以看到,mm的值輸出直接變成了0,為什么會有這種結果呢?
1 1 1 1 , 1 1 1 1
上面是我們的8個位元位,這個是255的二進制表示,當這個數加1的時候,最后一位加1,學過二進制的朋友都知道,依次從后往前滿2進1,最后的結果是:
1, 0 0 0 0, 0 0 0 0
由于我們只能讀取8個位元位,所以讀取之后的值就是
0 0 0 0, 0 0 0 0
這個值就是0,所以m后8位讀取變成了0,
為了驗證我們的結論,我們再次修改代碼:
function flow() public pure returns(uint8){
uint8 mm = 255;
mm++;
mm++;
return mm;
}
運行結果:

可以看到,當我們讓mm在之前的基礎上再加1之后,變成了
0 0 0 0, 0 0 0 1
所以mm的結果就是1,可以驗證我們剛剛的結論是正確的,
- 我們再寫一個函式,附上代碼:
function erroTest() public pure returns(int){
int a1 = 1;
int a2 = 0;
return a1/a2;
}
注意觀察上面的函式,很明顯我們看到上面的函式發生了錯誤,因為0不能做除數,那我們編譯這個代碼是能通過的,但是當我們呼叫這個函式的時候就會看到以下欄位

這就是發生了一個例外,
注意:solidity目前不支持小數型別
3.位元組陣列
我們還是先給一段代碼
pragma solidity ^0.4.0;
contract BytesArray {
bytes1 public num1 = 0x7a;// 只有一個位元組的數 二進制表示:0111 1010
bytes2 public num2 = 0x7a68;// 有兩個位元組的數 二進制表示:0111 1010 0110 1000
function getLength() public returns(uint256) {
return num1.length;// length屬性不可修改
}
function getLength2() public returns(uint256) {
return num2.length;// length屬性不可修改
}
}
- 位元組陣列雖然在存盤上與int一致,但是不能直接進行加減乘除操作,但是可以進行數的比較(>,>=,==,<=,<),也可以進行位運算(&, |, ~, ^, <<, >>),
- 當屬性添加public后,會被默認生成一個獲取該屬性的get方法,
- 加上以下代碼,驗證上述說法,f分別求&, |, ~, ^, <<, >>位運算后的值,并回傳,
function and() public returns(bytes2 n1,bytes2 n2,bytes2 n3, bytes2 n4, bytes2 n5,bytes2 n6){
return (num1&num2,num1|num2,~num1,num1^num2,num1<<1,num1>>1);
}
得到結果:

結果正確,
4.動態位元組陣列
上代碼:
pragma solidity ^0.4.0;
contract BytesArray {
bytes public name = new bytes(2);
function initName() public {
name[0] = 0x7a;
name[1] = 0x68;
}
function getLength() public returns(uint256){
return name.length;
}
function changeLength() public {
name.length = 5;
}
}
-
運行initName之后,再查看name屬性的值:

結果沒問題 -
運行getLength()方法查看bytes陣列的長度:

長度是2,結果正確
- 運行changeLength()方法修改bytes陣列的長度:


長度變成了5
總結:動態位元組陣列能夠修改陣列的長度,
- name.push(0x99)向name動態位元組陣列中添加一個0x99的元素,
4.string型別
- string操作與java基本一致,string余額bytes之間可以強制轉換,這一特性可以用來訪問string中特定位置的值,
代碼測驗
pragma solidity ^0.4.0;
contract StringTest {
string public name = "zhangsan";
function getLength() public returns(uint256){
return bytes(name).length;
}
function changeName() public {
bytes(name)[0] = 'L';
}
function getCName() public returns(bytes1){
return bytes(name)[0];
}
}
- 獲取name:

- 獲取長度為8個位元組:

- 呼叫getCName()獲取第一個字母:

6.呼叫changeName修改第一個字母之后再獲取name:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/245732.html
標籤:區塊鏈
