清理变量

最终,EVM 中的所有值都存储在 256 位字中。因此,在某些情况下,当值的类型小于 256 位时,需要清理剩余的位。Solidity 编译器被设计为在任何可能受到剩余位中潜在垃圾影响的操作之前执行此类清理。例如,在将值写入内存之前,需要清除剩余的位,因为内存内容可用于计算哈希值或作为消息调用的数据发送。类似地,在将值存储在存储器中之前,需要清除剩余的位,否则可能观察到混乱的值。

请注意,通过内联汇编进行访问不被视为此类操作:如果您使用内联汇编访问小于 256 位的 Solidity 变量,编译器不保证该值已正确清理。

此外,如果紧随其后的操作不受影响,我们不会清理位。例如,由于任何非零值都被 JUMPI 指令视为 true,因此我们不会在布尔值用作 JUMPI 条件之前清理它们。

除了上述设计原则之外,Solidity 编译器在将输入数据加载到堆栈时会清理它。

下表描述了应用于不同类型的清理规则,其中 higher bits 指的是类型小于 256 位时的剩余位。

类型

有效值

无效值的清理

具有 n 个成员的枚举

0 到 n - 1

抛出异常

布尔

0 或 1

变为 1

有符号整数

将更高的位设置为符号位

目前静默符号扩展到有效值,即所有更高的位都设置为符号位;将来可能会抛出异常

无符号整数

更高的位为零

目前静默屏蔽到有效值,即所有更高的位都设置为零;将来可能会抛出异常

请注意,有效值和无效值取决于它们的大小。考虑 uint8,无符号 8 位类型,它具有以下有效值

0000...0000 0000 0000
0000...0000 0000 0001
0000...0000 0000 0010
....
0000...0000 1111 1111

任何无效值都会将其更高的位设置为零

0101...1101 0010 1010   invalid value
0000...0000 0010 1010   cleaned value

对于 int8,有符号 8 位类型,有效值为

负数

1111...1111 1111 1111
1111...1111 1111 1110
....
1111...1111 1000 0000

正数

0000...0000 0000 0000
0000...0000 0000 0001
0000...0000 0000 0010
....
0000...0000 1111 1111

编译器将 signextend 符号位,负数为 1,正数为 0,覆盖更高的位

负数

0010...1010 1111 1111   invalid value
1111...1111 1111 1111   cleaned value

正数

1101...0101 0000 0100   invalid value
0000...0000 0000 0100   cleaned value