值类型

值类型,指该类型的值,无论是用作函数参数,还是用于赋值,其值总是按值传递。

对于值类型的变量而言,状态变量总是存储在 storage 中,而局部变量总是存储在 memory 中。

布尔类型 bool

布尔类型只有两种可能的值(布尔值): true 表示逻辑上的真,false 表示逻辑上的假。布尔值的零值false

用比较运算符对两个值的比较,如果成立,结果为 true,否则,结果为 false

可用于一个布尔值的运算符包括:! 逻辑非;以用于两个布尔值之间的运算符包括:&& 逻辑与、|| 逻辑或、== 相等、!= 不相等。

注意:

Solidity 与其他常见语言一样 ,&&逻辑与、||逻辑或的运算都遵循短路求值规则,即若求值结果已经确定,程序将不会对表达式剩余的部分进行求值,那一部分的代码将不会执行。


整数类型 intuintintNuintN

intNuintN 中的 N 是 8 到 256 之间任意 8 的倍数,表示该类型占用的的二进制位数。intuint 分别是 int256uint256 的别称。

可与整数结合的前缀运算符包括:

  • 位运算符:~按位取反;
  • 算术运算符:-负、+正。

可用于两个整数之间的运算符包括:

  • 比较运算符:<=小于等于、<小于 、== 等于、!=不等于、>=大于等于、>大于;
  • 位运算符:&按位与、|按位或、^按位异或;
  • 算术运算符:+加、-减、*乘、/除、%求模、**求幂、<<左移、>>右移。

注意:

  • 除法总是整除,但有一个例外:两个运算元都是字面量或字面表达式,在需要将一个字面量/字面表达式数值转换为非字面量之前,Solidity 会一直保证此字面量/字面表达式的精确。
  • 除以零或用零求模会抛出运行时异常。
  • 位移是算数位移,若位移运算的右运算元小于零,将会抛出运行时异常。
定点小数类型 fixedufixedfixedMxNufixedMxN

注意:

编写本书时,Solidity 仅支持声明定点小数,而声明出的定点小数甚至不能赋值。读者阅读本书时应查阅 Solidity 官方文档以获知此类型是否已被新版本完全支持。

fixedMxNufixedMxN 中,M是从 8256 之间,8 的倍数,表示该类型占用的的二进制总位数;N是从 080 之间任意的整数,表示该类型小数部分所占用的二进制位数。fixedufixedz 分别是 ufixed128x18fixed128x18 的别称。

可与 定点小数的前缀运算符包括:

  • 算术运算符:-负、+正。

可用于两个 定点小数之间的运算符包括:

  • 比较运算符:<=小于等于、<小于 、== 等于、!=不等于、>=大于等于、>大于;
  • 算术运算符:+加、-减、*乘、/除、%求模。
有理数与整数的字面量 (Rational and Integer Literals)
  • 十进制整数常量由一串范围在 09 之间的数字组成。Solidity 不允许此类数字序列以 0 开头,也不八进制字面量。如:42
  • 小数由一个 . 及点的两边至少一边紧挨着的数字确定而成。如:1.11..1
  • Solidity 同样支持科学计数法,尾数部分可以是分数,而指数部分只能是整数。如:-1.5e-2
  • 在需要将字面量/字面表达式数值转换为非字面量之前,Solidity 会保证这些字面量/字面表达式的精确。只要这些字面量/字面表达式仍然是整数,就可以对它们应用任意的运算符。

地址类型 address

地址是一种长度为 20 字节的数据类型(通常用来存放以太坊中的地址)。

注意:

Solidity 0.5.0 之前,所有合约都被视为继承自地址类型。将来 0.5.0 发布后将不在这么处理,不过合约依旧可以显式转换为地址。

可用于两个地址之间的运算符包括:

  • 比较运算符:<=小于等于、<小于 、== 等于、!=不等于、>=大于等于、>大于;
地址包含的成员
  • balance 属性和 transfer 函数

地址的 balance 属性用于查询一个地址所拥有的以太坊余额,以 wei 为单位。

地址的 transfer 则是从合约向一个地址转账以太坊的主要方法,同样以 wei 为单位。

以下是官方文档中给出的示例:

address x = 0x123;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);

提示:

向一个合约地址转账,总是会一起调用该被转账合约的回退函数 (fallback function) 。若执行该函数消耗光了所有的 gas,以太坊转账将会被回退,调用转账函数的当前合约会抛出异常并终止。

  • send 函数

地址的 send 函数功能与 transfer 函数类似,但更底层。若 send 执行失败,send 将返回 false,而不会导致调用该函数的当前合约抛出异常并终止。

注意:

若递归栈深度超过 1024 层,或转账接受者用尽了 gassend 函数便会失败。若要保证安全地转移以太坊,一定要始终检查 send 函数的返回值,或者使用 transfer 函数。此外,还有一种更好的办法:用转账接收者自行提取以太坊的模式设计合约。

  • call 函数 、callcode 函数与 delegatecall 函数

这三个函数是用来手动调用合约函数的函数,十分底层。

目前先跳过这一部分内容,在函数一节会详细讲解这三个函数。

地址字面量 (Address Literals)

所有通过地址校验和测试(由 EIP-55 定义)的以 0x 开头的十六进制字面量被视作地址字面量,其类型为地址类型。

除去前缀,长度在 3941 之间,但未能通过校验和的十六进制常量会被视为有理数常量。为安全起见,编译器会为此给出警告。


字节与定长字节数组 byte bytesI

bytesI 中的 I 是 1 到 32 之间的任意整数,表示该类型占用的字节数(或者说 I * 8 二进制位数)。字节(byte )实际上是 byte1 的别称。

可用于两个定长字节数组之间的运算符包括:

  • 比较运算符:<=小于等于、<小于 、== 等于、!=不等于、>=大于等于、>大于;
  • 位运算符:&按位与、|按位或、^按位异或;

此外,定长字节数组还支持以下运算符:

  • 索引访问 (Index access):如果 x 的类型为 bytesI,满足 0 <= k < I 的表达式 x[k] 返回该数组第 k + 1 个字节的值(只可读不可写)。
  • 位移运算符:定长字节数组做左运算元。右运算元需为整数类型,代表要位移的位数,若其小于零,将会抛出运行时异常。返回的结果是左运算元整体位移的结果,其类型与左运算元一致。

定长字节数组包含的成员有:

  • length:数组的固定长度,即其固定的字节数。只读。

提示:

本书之后会讲到的变长数组中,用 byte[] 也可以存放多个字节,但这样会浪费很大的空间—其作为调用参数传递时,数组的每一个元素占用 32 个字节,但实际用到的只有 1 字节。对于变长字节数组,应该用特定的类型 bytes

字符串字面量 (String Literals)

字符串字面量被 ' 单引号或 " 双引号所包围。与 C 语言风格字符串不同,Solidity 中的字符串末尾没有 '\0' 终结符。例如, "foo" 只占用 3 字节,而非 4 字节。

字符串常量支持转义字符,如 \n\xNN\uNNNN\xNN 会插入与对应十六进制相应的字符,而 \uNNNN 则会通过所给 Unicode 码位插入相应的 UTF-8 序列。

只要容量足够,字符串常量可以隐式转换为定长字节数组(bytes1bytes32),变长字节数组(bytes)或字符串(string)。后两种类型会在引用类型一节中提到。

还应注意:

字符串本质是utf8编码的字节数组,因此判断字符串长度时要先做转换:

bytes(str).length == 0
字符串式的十六进制字面量 (Hexadecimal Literals)

字符串式的十六进制字面量以 hex 为前缀,紧跟着一对双引号及此双引号所围内容,如:hex"89ABCDEF"

字符串式的十六进制字面量的长度必须为 2 的倍数,从高到低,每 2 位表示一个字节。其行为与字符串字面量相似,从前往后占用数组空间,这是一组例子:

// a: 0x00000000abcd
// 0xABCD 是被视作整数,以整数类型的规则隐式转换为字符数组
bytes6 a = 0xABCD;

// b: 0xabcd00000000
// hex"ABCD" 以与字符串字面量相似的规则隐式转换为字符数组
bytes6 b = hex"ABCD";

// c: 43981 <=> 0x00000000abcd
// hex"ABCD" 作为整体隐式转换为整型
int48 c = hex"ABCD";

十六进制字面量拥有和字符串常量相同的类型转换限制。


自定义枚举类型 (enum)

枚举是 Solidity 中定义用户自定义类型的一种方式,只能在函数外定义。

枚举值可以与任意的整数类型相互进行显式转换,但是并不能被隐式转换。显式转换时,运行时会检查值的范围,如果不在范围内,将会抛出异常。

枚举至少需要一位有成员。

定义枚举的形式如下(末尾不能有分号):

enum 枚举名 { 枚举项A, 枚举项B, ... }

例如:

enum RGB {
    Red,
    Green,
    Blue
}

枚举的主要使用方法可参见下例:

function test() public pure returns(bool) {

    // 声明相应枚举类型的变量,并赋值特定的枚举项
    RGB myColor = RGB.Blue;

    // 枚举和整数类型间的显式类型转换
    RGB myNewColor = RGB((uint8(myColor)+1) % 3);

    // 判断变量的值是否是特定的枚举项
    if (myNewColor == RGB.Red) {
        return false;
    }
    return true;
}

函数的类型 (Function Types)

函数类型也是一种值类型,相关内容可阅读本书有关函数的部分。

results matching ""

    No results matching ""