操作符
即使两个操作数的类型不同,也可以应用算术和位运算符。例如,您可以计算:y = x + z,其中x是 uint8并且z类型为int32。在这些情况下,将使用以下机制来确定计算运算的类型(这在溢出的情况下很重要)和运算符结果的类型:
- 如果右操作数的类型可以隐式转换为左操作数的类型,则使用左操作数的类型,
- 如果左操作数的类型可以隐式转换为右操作数的类型,则使用右操作数的类型,
- 否则,该操作是不允许的。
如果其中一个操作数是文字数字,则首先将其转换为其“移动类型”,这是可以保存该值的最小类型(相同位宽的无符号类型被认为比有符号类型“更小”) . 如果两者都是文字数字,则以任意精度计算操作。
运算符的结果类型与执行运算的类型相同,但结果始终为 bool
的比较运算符除外。
运算符**(取幂),<< 并>>使用左操作数的类型进行运算和结果。
三元运算符
三元运算符用于<expression> ? <trueExpression> : <falseExpression>
形式的表达式。它根据 main <expression>的评估结果评估后两个给定表达式之一。如果评估为true,则将被评估<trueExpression>,否则将被评估<falseExpression>
。
三元运算符的结果没有有理数类型,即使它的所有操作数都是有理数文字。结果类型由两个操作数的类型以与上述相同的方式确定,如果需要,首先转换为它们的移动类型。
结果,将由于算术溢出而恢复。原因是is of type ,它也强制执行加法,并且 256 超出了该类型允许的范围。255 + (true ? 1 : 0)
(true ? 1 : 0)
uint8
uint8
另一个结果是表达式 like是有效的,但不是。这是因为前者是一个无限精确计算的有理表达式,只有它的最终值才重要。后者涉及将小数有理数转换为整数,目前是不允许的。1.5 + 1.5
1.5 + (true ? 1.5 : 2.5)
复合和递增/递减运算符
如果a
是一个 LValue(即一个变量或可以赋值的东西),以下运算符可用作简写:
a += e
相当于。运算符, , , , , , ,和相应定义。和等价于/但表达式本身仍然具有. 反之,和有同样的效果,但返回改变后的值。a = a + e
-=
*=
/=
%=
|=
&=
^=
<<=
>>=
a++
a--
a += 1
a -= 1
a
--a
++a
a
删除
delete a
将类型的初始值分配给a
。即对于整数,它等价于,但它也可用于数组,其中它分配长度为零的动态数组或相同长度的静态数组,所有元素都设置为其初始值。删除数组索引处的项目,并保留所有其他元素和数组的长度不变。这尤其意味着它会在阵列中留下空隙。如果您打算删除项目,映射可能是更好的选择。a = 0
delete a[x]
x
对于结构,它分配一个所有成员都重置的结构。换句话说,a
after的值与在没有赋值的情况下声明if 的值相同,但需要注意以下几点:delete a
a
delete
对映射没有影响(因为映射的键可能是任意的并且通常是未知的)。因此,如果您删除一个结构,它将重置所有不是映射的成员,并且还会递归到成员中,除非它们是映射。但是,可以删除单个键及其映射的内容:如果a
是映射,则将删除存储在的值。delete a[x]
x
需要注意的是,它的行为实际上类似于对 的赋值,即它在 中存储了一个新对象。当引用变量时,这种区别是可见的:它只会重置自己,而不是之前引用的值。delete a
a
a
a
a
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract DeleteExample { uint data; uint[] dataArray; function f() public { uint x = data; delete x; // sets x to 0, does not affect data delete data; // sets data to 0, does not affect x uint[] storage y = dataArray; delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also // y is affected which is an alias to the storage object // On the other hand: "delete y" is not valid, as assignments to local variables // referencing storage objects can only be made from existing storage objects. assert(y.length == 0); } }