清理变量

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

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

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

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

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

Type

Valid Values

Cleanup of Invalid Values

enum of n members

0 until n - 1

throws exception

bool

0 or 1

results in 1

signed integers

higher bits set to the sign bit

currently silently signextends to a valid value, i.e. all higher bits are set to the sign bit; may throw an exception in the future

unsigned integers

higher bits zeroed

currently silently masks to a valid value, i.e. all higher bits are set to zero; may throw an exception in the future

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

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

任何无效值的高位将被设置为零:

0101...1101 0010 1010   无效值
0000...0000 0010 1010   清理后的值

对于 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   无效值
1111...1111 1111 1111   清理后的值

正值

1101...0101 0000 0100   无效值
0000...0000 0000 0100   清理后的值