Skip to main content

Solidity 字面值

字面值(literal)是指在程序中无需变量保存,可直接表示为一个具体的数字或字符串的值。Solidity支持多种字面值类型,包括:

  • 地址字面值
  • 有理数和整数字面值
  • 字符串字面值
  • Unicode字面值

我们接下来对它们逐一进行介绍。

地址字面值(address literal)

地址字面值是一个长度为42字节的十六进制字符串。形如 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990 就是一个地址字面值。地址字面值可以直接赋值给地址类型:

地址字面值赋值给地址类型
address addr = 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990;
试一试 »

有理数和整数字面值

Solidity支持多种有理数和整数的字面值表示方式:

  • 十进制整数:例如123
  • 十进制小数:例如.11.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.5a 进行了运算,所以编译器会尝试将 2.5 转换成 uint128 类型。不过因为类型不匹配,编译器会报错。

有理数和整数字面值参与运算时会被转换成非字面值类型(1)
uint128 a = 1;
uint128 b = 2.5 + a + 0.5; //编译报错
试一试 »

但是如果你把代码改成下面这个样子你会得到 b=4 的结果。这是因为两个字面值 2.5 + 0.5 先进行了运算,得到 3 ,然后将 3 转换成 uint128 ,再与 a 进行运算,最后得到 4

有理数和整数字面值参与运算时会被转换成非字面值类型(2)
uint128 a = 1;
uint128 b = 2.5 + 0.5 + a;
试一试 »

再调换一下 a 的位置,编译器也会报错,这是因为 a2.5 先结合运算,所以需要将 2.5 转换成 uint128 ,因为类型不匹配,所以报错。

有理数和整数字面值参与运算时会被转换成非字面值类型(3)
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:

使用unicode字面值
string memory a = unicode"Hello \u0041 😃";
试一试 »

小结

  1. 字面值(literal)是在程序中无需变量保存的值,可以直接表示为数字或字符串。Solidity支持多种字面值类型:地址字面值,有理数和整数字面值,字符串字面值,Unicode字面值。
  2. 地址字面值是一个长度为42字节的十六进制字符串,可以直接赋值给地址类型。
  3. 有理数和整数字面值有多种表示方式:十进制整数,十进制小数,十六进制整数,科学记数法。Solidity 不支持8进制字面值。
  4. 在 Solidity 中,可以在整数字面值中使用下划线_来增强可读性。例如,1_000_000 表示 100万。
  5. 字符串字面值是由双引号 " 或单引号 ' 括起来的字符串。可以使用转义字符 \ 来表示一些特殊字符。
  6. Unicode字面值是由反斜杠 \ 和四位十六进制数拼成的。例如,\u0041 表示大写字母 A