Solidity 字面值
字面值(literal)是指在程序中无需变量保存,可直接表示为一个具体的数字或字符串的值。Solidity支持多种字面值类型,包括:
- 地址字面值
- 有理数和整数字面值
- 字符串字面值
- Unicode字面值
我们接下来对它们逐一进行介绍。
地址字面值(address literal)
地址字面值是一个长度为42字节的十六进制字符串。形如 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990
就是一个地址字面值。地址字面值可以直接赋值给地址类型:
address addr = 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990;
有理数和整数字面值
Solidity支持多种有理数和整数的字面值表示方式:
- 十进制整数:例如
123
- 十进制小数:例如
.1
,1.2
等;但是不能是1.
因为其限制小数点后面必须至少跟一个数字 - 十六进制整数:例如
0xff
- 科学记数法:例如
2e10
,-2e10
,2e-10
,2.5e1
uint256 d1 = 123; // d1=123
uint256 d2 = .1+1.9; // d2=2
uint256 h = 0xff; // h=255
int256 s1 = 2e10; // s1=20000000000
int256 s2 = -2e10; // s2=-20000000000
注意在Solidity中是不支持8进制字面值的,所以不要使用8进制的字面值表示方式。
有时候你会注意到有些合约里面的整数字面值带下划线 _
。它们仅仅用来做视觉辅助,不会对数值有什么影响。例如 1000_000
是100万。
有理数和整数字面值可以是任意精度
值得一提的是,所有的有理数和整数字面值可以是任意精度,不会有精度损失的问题。例如下面的例子中, p
的值为 1
。虽然其计算过程的中间值 (2**800 + 1)
已经超过了 uint256
可以表示的范围,但是整个表达式的最后结果是 1
。同理再举一例: .5*8
的结果为 4
。
uint256 p = (2**800 + 1) - 2**800;
但是要注意一个规则:只要字面值和非字面值进行了运算,那么字面值就会被尝试转换成非字面值的类型。例如下面这个表达式, 2.5
与 a
进行了运算,所以编译器会尝试将 2.5
转换成 uint128
类型。不过因为类型不匹配,编译器会报错。
uint128 a = 1;
uint128 b = 2.5 + a + 0.5; //编译报错
但是如果你把代码改成下面这个样子你会得到 b=4
的结果。这是因为两个字面值 2.5 + 0.5
先进行了运算,得到 3
,然后将 3
转换成 uint128
,再与 a
进行运算,最后得到 4
;
uint128 a = 1;
uint128 b = 2.5 + 0.5 + a;
再调换一下 a
的位置,编译器也会报错,这是因为 a
和 2.5
先结合运算,所以需要将 2.5
转换成 uint128
,因为类型不匹配,所以报错。
uint128 a = 1;
uint128 b = a + 2.5 + 0.5 ; //编译报错
字符串字面值
字符串字面值定义
字符串字面值用单引号 ’’
或者双引号 ””
定义。如下所示:
string memory s1 = "This is a string"; // 双引号
string memory s2 = 'This is a string'; // 单引号
与C语言不同的是,Solidity的字符串字面值后面不会跟 \0
。例如 ”foo”
是三个字节,而不是四个字节。
隐式类型转换
字符串字面值可以隐式地转换成 bytes1, bytes2, …, bytes32
还有 string
类型。所以可以直接对它们进行赋值。如下所示:
bytes1 b1 = "b";
bytes2 b2 = "b2";
bytes3 b3 = "b3";
bytes32 b32 = "b32";
string memory str = "string";
转义字符
除此之外,字符串字面值还支持下列转义字符:
\<newline>
(字符串字面值可以横跨多行)\\
(反斜杠)\'
(单引号)\"
(双引号)\n
(新行)\r
(回车)\t
(tab)\xNN
(十六进制表示字符)\uNNNN
(unicode表示字符)
这些转义字符可以和其他字符混合使用,例如 ”\’hello world\’”
。
Unicode字面值
Unicode字面值和字符串字面值差不多,只需要在前面加上 unicode
关键字你就可以在里面包含任何的UTF-8字符。Unicode字面值是由反斜杠 \
和四位十六进制数拼成的。例如, \u0041
表示大写字母 A。同时,你也可以使用Emoji:
string memory a = unicode"Hello \u0041 😃";
小结
- 字面值(literal)是在程序中无需变量保存的值,可以直接表示为数字或字符串。Solidity支持多种字面值类型:地址字面值,有理数和整数字面值,字符串字面值,Unicode字面值。
- 地址字面值是一个长度为42字节的十六进制字符串,可以直接赋值给地址类型。
- 有理数和整数字面值有多种表示方式:十进制整数,十进制小数,十六进制整数,科学记数法。Solidity 不支持8进制字面值。
- 在 Solidity 中,可以在整数字面值中使用下划线
_
来增强可读性。例如,1_000_000
表示 100万。 - 字符串字面值是由双引号
"
或单引号'
括起来的字符串。可以使用转义字符\
来表示一些特殊字符。 - Unicode字面值是由反斜杠
\
和四位十六进制数拼成的。例如,\u0041
表示大写字母A
。