表达式与控制结构
赋值
结构化赋值与返回多个值
Solidity 内部支持元组类型(tuple types),即由多个(可能类型不同)且数量在编译时已知的元素构成的列表。元组通常用于一次性返回多个值。这些返回值既可以赋值给新声明的变量,也可以赋值给已有变量(或更广义上的左值 LValues)。
须要注意的是,元组在 Solidity 中并不是一种独立的类型,它们仅作为表达式的一种语法组合存在。
- // SPDX-License-Identifier: GPL-3.0
- pragma solidity >=0.5.0 <0.9.0;
- contract C {
- uint index;
- function f() public pure returns (uint, bool, uint) {
- return (7, true, 2);
- }
- function g() public {
- // 用类型声明变量并从返回的元组中赋值,
- // 不需要指定所有元素(但数量必须一致)。
- (uint x, , uint y) = f();
- // 交换变量值的常见技巧 —— 不适用于非值类型的存储变量。
- (x, y) = (y, x);
- // 可以省略部分组件(也适用于变量声明)。
- (index, , ) = f(); // 设置 index 为 7
- }
- }
复制代码 不答应将变量声明与非声明赋值混用,例如以下写法是无效的:(x, uint y) = (1, 2);
注意:当元组涉及引用类型(如数组、结构体等)时,进行多变量赋值时可能会引发非预期的复制举动,应特别警惕使用。在这种情况下,赋值过程可能不会像预期那样浅拷贝或引用传递,可能导致逻辑错误或意外副作用。
数组和结构体的赋值复杂性
对于非值类型(如数组和结构体,包括 bytes 和 string),赋值的语义更为复杂,特别是在涉及内存(memory)与存储(storage)之间的数据传递时。
在下面的例子中,函数 g(x) 的调用不会改变 x,因为 x 会被复制到内存中;而 h(x) 则可以成功修改 x,因为它是通过引用传递的:
- // SPDX-License-Identifier: GPL-3.0
- pragma solidity >=0.4.22 <0.9.0;
- contract C {
- uint[20] x;
- function f() public {
- g(x);
- h(x);
- }
- function g(uint[20] memory y) internal pure {
- y[2] = 3;
- }
- function h(uint[20] storage y) internal {
- y[3] = 4;
- }
- }
复制代码 解析如下:
- g(x):传入的是 memory 类型的副本,对 y[2] 的修改不会影响原始的 x。
- h(x):传入的是 storage 引用,对 y[3] 的修改将直接影响合约状态变量 x[3]。
这表现了 Solidity 中引用类型的核心举动:memory 会创建副本,storage 会引用原始数据。
因此,在处置惩罚数组和结构体等引用类型时,务必明白所用的数据位置(data location),以避免产买卖料之外的副作用或逻辑错误。
作用域和声明
在 Solidity 中,变量在声明后将具有其类型对应的默认初始值,其字节表现为全零。这个“默认值”通常是该类型的典范“零状态”。例如,bool 类型的默认值为 false,而 uint 和 int 类型的默认值则为 0。对于定长数组以及 bytes1 至 bytes32,每个元素都将被初始化为其对应类型的默认值。对于动态数组、bytes 和 string 类型,默认值为空数组或空字符串。enum 类型的默认值为其界说中的第一个成员。
Solidity 的作用域规则遵循 C99(以及很多其他编程语言)中广泛采用的标准规则:变量从声明之后立即开始可见,直至包含该声明的最内层 {} 块结束为止。唯一的例外是 for 循环的初始化部门中声明的变量,其作用域仅限于整个 for 循环结构之内。
与参数相干的变量(如函数参数、修饰符参数、catch 参数等)在其所在的代码块中是可见的:函数和修饰符的参数在整个函数体或修饰符体内均可访问;catch 语句中的参数则仅在对应的 catch 块中可见。
在代码块之外声明的元素(如状态变量、函数、合约、用户界说类型等)即便在声明之前也可以被访问。这意味着状态变量可以在其界说之前被使用,函数也可以在界说前进行递归调用。
因此,下面的示例可以正常编译而不会产生任何警告,尽管两个变量使用了雷同的名称,但由于它们处于互不重叠的作用域中,因此不会冲突:
- // SPDX-License-Identifier: GPL-3.0
- pragma solidity >=0.5.0 <0.9.0;
- contrac
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |