0%

solidity | 基础变量

这一章主要是对 solidity 这个语言特性的一些总结。

  • 静态语言
    • 编译前变量类型需要确认
  • 值类型
    • 布尔类型
    • 整型
    • 定长浮点型
    • 定长字节数组
    • 有理数和整型常量
    • 字符串常量
    • 十六进制常量
    • 枚举
    • 函数类型
    • 地址类型
    • 地址常量

public|private|internal 也可用于修饰状态变量。

public 变量会自动生成同名的 getter 函数,用于查询数值。

没有标明可见性类型的状态变量,默认为 internal

布尔类型

  • bool
    • true/false
    • 支持运算
      • ! && != || == 「支持短路」
1
2
3
4
5
6
7
8
9
10
pragma solidity ^0.4.0;

contract TestBool{
bool a = true;
bool b = false;

function test1() public constant returns(bool){
return a == b;
}
}

整型

  • int
    • int8 int16int256 「数字表示类型所占空间的位数」
  • uint 无符号,只能大于 0
    • uint8 uint16uint256

运算

  • /(除)
    • 截断,除 0 会抛出异常
  • x << y
    • 和乘等价,左移一位相当于乘以 2
  • x >> y
    • 和除等价,右移一位相当于除以 2
  • a++
  • a--
  • a += c
1
2
3
4
5
6
7
8
9
10
11
12
13
pragma solidity ^0.4.0;

contract TestInt{
int8 a = -1;

function add(uint x, uint b) public pure returns(uint){
return x + b;
}

function add2(uint x, uint b) public pure returns(uint z){
z = x + b;
}
}

上面 addadd1 作用是相同的。

溢出问题

1
2
3
4
5
6
7
8
uint8 x = 0x80;
uint8 y = x * 2; // y 溢出为 0

uint8 m = 0xo1;
uint8 n = m - 1; // n 溢出为 255

uint256 a = 2 ** 256 -1;
uint256 b = a + 1; // 溢出为 0

解决溢出

  • assert
  • SafeMath「库」

assert

1
2
3
4
5
6
7
8
9
10
pragma solidity ^0.4.18;

contract TestInt{

function add(uint8 a, uint8 b) public returns (uint8){
uint8 c = a + b;
assert(c >= a);
return c;
}
}

不满足 assert 会抛出异常。

定长浮点型 「暂时无法使用」

  • fixed
  • ufixed

由于 solidity 对空间要求非常严格,所以,我们需要声明浮点型所占空间。

  • fixedM*N
    • M : 位数 以 8 步进, 8 -256
    • N : 小数点位数 为 0 - 80

定长字节数组

占空间的固定数组,后面跟着的数字表示为字节。之前的类型表示的都是位。

  • bytes1
  • bytes2
  • bytes8
  • bytes32
    • .length 获取字节数组长度

如果后面没有接数字,表示为 bytes1

1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.18;

contract TestInt{
bytes1 bt1 = 0x01;
bytes2 bt2 = "zb";

function get_length() public constant returns(uint){
return bt2.length;
}

}

另外,bytes 可以像 string 一样存储字符串,并且,由于 string 不是定长的,而 bytes 可以定长,所以,bytes 需要的存储更小。

bytes 支持整型运算,比如 > < = 还支持位运算。

bytes 还可以像数组一样索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pragma solidity ^0.4.18;

contract TestInt{
bytes2 bt2 = "zb";

function get_bytes() public constant returns(uint){
return (uint)(bt2[0]);
}

function get_byte() public constant returns(byte){
return bt2[0];
}

}

常量

数字常量

概念和其他语言一样,需要注意的是,在计算过程中,常量不会截断也不会溢出

1
2
uint a = 5/2 + 5/2; // 5
uint b = (2 ** 800) + 1 - (2 ** 800) // 1

变量是不能和常量一起运算的。

1
2
uint a = 1;
uint b = 2.5 + a; // 这句是错误的

字符串常量

支持转译字符。

1
2
3
\n
\x61
\u718A
  • 不支持拼接
    • "abc" + "d" // 错误

16 进制常量

表达式中直接出现的字符串:内容是 16 进制数

  • hex"001122f"
    • 可以转化为 bytes
1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.18;

contract TestInt{
bytes2 bt2 = "zb";

function get_byte() public constant returns(bytes2,bytes1,bytes1){
bytes2 a = hex"aabb";
return (a,a[0],a[1]);
}

}

枚举

  • 可以与整型进行转换,但是,必须是强制类型转换
  • 枚举至少需要一个成员
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pragma solidity ^0.4.18;

contract TestInt{

enum Action {L,R,U,D}
Action choice;
Action choice2 = Action.L;

function set() {
choice = Action.R;
}

function get() public constant returns (uint){
return (uint)(choice2);
}
}

地址类型

  • address
    • 表示一个地址类型 20 字节
    • 不需要双引号
  • 成员
    • .balance 单位是 wei
  • 函数
    • transfer()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pragma solidity ^0.4.18;

contract TestInt{

constructor() payable{

}

function get_balance(address a) public constant returns(uint){
return a.balance;
}

// 查看合约地址
function get() public constant returns(uint){
address a = this;
return a.balance;
}
}

transfer

这个中文意思是转移,但是,使用起来更像是接收的意思。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pragma solidity ^0.4.18;

contract TestInt{

constructor() payable{

}

function get() public constant returns(uint){
address a = this;
return a.balance;
}

function transfer(address a) public{
address receiveAddress = a;
address t = this;

if(t.balance > 1e18){
receiveAddress.transfer(1e18);
}
}
}

上面如果运行 trnasfer 其作用是 合约地址转 1etha 地址。

更加细节的用法参考

请我喝杯咖啡吧~