阅读(4763) (15)

范围和声明

2022-05-12 15:16:30 更新

声明的变量将具有一个初始默认值,其字节表示全为零。变量的“默认值”是任何类型的典型“零状态”。例如,a 的默认bool 值为false。uint或int 类型的默认值为0。对于静态大小的数组和bytes1to 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;
contract C {
    function minimalScoping() pure public {
        {
            uint same;
            same = 1;
        }

        {
            uint same;
            same = 3;
        }
    }
}

作为 C99 范围规则的一个特殊示例,请注意,在下文中,第一次赋值x将实际分配外部变量而不是内部变量。在任何情况下,您都会收到有关外部变量被遮蔽的警告。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;
// This will report a warning
contract C {
    function f() pure public returns (uint) {
        uint x = 1;
        {
            x = 2; // this will assign to the outer variable
            uint x;
        }
        return x; // x has value 2
    }
}

警告

在 0.5.0 版本之前,Solidity 遵循与 JavaScript 相同的范围规则,也就是说,在函数内任何地方声明的变量都将在整个函数的范围内,无论它在哪里声明。以下示例显示了一个用于编译但从 0.5.0 版本开始导致错误的代码片段。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;
// This will not compile
contract C {
    function f() pure public returns (uint) {
        x = 2;
        uint x;
        return x;
    }
}