清理变量
最终,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 清理后的值