solidity 中的状态变量是什么?
what are state variables in solidity?
我阅读了一些关于 storage
、memory
和 view
、pure
的文档,但我并不完全理解它们。我有以下代码:
contract {
struct Random {
uint32 state;
uint8 i;
}
function main() pure internal {
Random rand = Random(seed, 0);
...
}
function get_rand(Random rand, uint8 n) pure internal returns (uint16) {
assert(n <= 16)
while (true) {
if (rand.i >= 8) {
rand.state = xorshift32(rand.state);
rand.i = 0;
}
uint8 r = uint8(rand.state >> (rand.i << 4)) & 0x0f;
rand.i += 1;
if (r < n) {
return r;
}
}
}
}
我的问题是:
1) main
中的局部变量应该标记为storage
还是memory
?我应该为 get_rand
中的参数标记什么?
2) 突变会起作用吗?说,我读到 pure
函数不能更改状态变量,并且会复制内存变量。将两者都标记为 storage
就足够了吗?如果 get_rand
改变了它的论点,我还应该声明 pure
吗?
谢谢
状态变量是永久存储在合约存储中的值。它们在契约范围内和函数范围外声明。像这样:
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
所以合约的整体层次结构是这样的:
Contract
--/ State Variables
--/ Functions
除此之外,我真的不明白你在问什么。也许你应该问清楚,并在不同的问题中,而不是在一个问题中含糊地问所有问题。
view
和 pure
是函数修饰符,描述了该函数中的逻辑将如何与合约状态交互。如果你的合约要从存储中读取,而不是写入,你将使用 view
(或 constant
完全相同)修饰符(参见 view functions documentation). If you're not going to read or write from contract state, and everything you do only works with memory variables, then it's a pure function.
Should I mark storage or memory for the local variable in main? And what should I mark for the argument in get_rand?
默认情况下,结构是 storage
变量,它会尝试将您的结构写入状态。这是你需要小心的地方,因为如果你在你应该使用 memory
的地方使用 storage
变量,你实际上可以覆盖你的状态。示例:
contract C {
uint _var;
function f() public {
Random r;
...
}
}
在这种情况下,r
是未初始化的存储指针,它导致变量指向存储槽 0。当您在结构 (r.state = 100;
) 中设置一些变量时,它将写入该值到插槽 0,其中 覆盖 _var
处的值。
当你想创建一个新的结构作为局部变量时,你想使用memory
修饰符,然后将其设置为状态变量(或将其添加到状态mapping/array) .当你想从 mapping/array 读取结构到局部变量时,使用 storage
.
对于您提供的示例,您想将其设置为 memory
变量。仔细阅读 Solidity 文档的 this section 。
Will the mutation work? Say, I read that a pure function cannot change state variables, and memory variables are copied. Is marking both as storage enough? Should I still declare pure for get_rand if it changes its argument?
不,它不会改变您的合同状态。虽然局部结构变量默认为 storage
,但函数参数默认始终为 memory
(即使是结构)。在 get_rand
中修改 rand
不会修改任何状态。如果您将函数更改为访问状态,您会因为 pure
修饰符而出现编译错误。
我阅读了一些关于 storage
、memory
和 view
、pure
的文档,但我并不完全理解它们。我有以下代码:
contract {
struct Random {
uint32 state;
uint8 i;
}
function main() pure internal {
Random rand = Random(seed, 0);
...
}
function get_rand(Random rand, uint8 n) pure internal returns (uint16) {
assert(n <= 16)
while (true) {
if (rand.i >= 8) {
rand.state = xorshift32(rand.state);
rand.i = 0;
}
uint8 r = uint8(rand.state >> (rand.i << 4)) & 0x0f;
rand.i += 1;
if (r < n) {
return r;
}
}
}
}
我的问题是:
1) main
中的局部变量应该标记为storage
还是memory
?我应该为 get_rand
中的参数标记什么?
2) 突变会起作用吗?说,我读到 pure
函数不能更改状态变量,并且会复制内存变量。将两者都标记为 storage
就足够了吗?如果 get_rand
改变了它的论点,我还应该声明 pure
吗?
谢谢
状态变量是永久存储在合约存储中的值。它们在契约范围内和函数范围外声明。像这样:
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
所以合约的整体层次结构是这样的:
Contract
--/ State Variables
--/ Functions
除此之外,我真的不明白你在问什么。也许你应该问清楚,并在不同的问题中,而不是在一个问题中含糊地问所有问题。
view
和 pure
是函数修饰符,描述了该函数中的逻辑将如何与合约状态交互。如果你的合约要从存储中读取,而不是写入,你将使用 view
(或 constant
完全相同)修饰符(参见 view functions documentation). If you're not going to read or write from contract state, and everything you do only works with memory variables, then it's a pure function.
Should I mark storage or memory for the local variable in main? And what should I mark for the argument in get_rand?
默认情况下,结构是 storage
变量,它会尝试将您的结构写入状态。这是你需要小心的地方,因为如果你在你应该使用 memory
的地方使用 storage
变量,你实际上可以覆盖你的状态。示例:
contract C {
uint _var;
function f() public {
Random r;
...
}
}
在这种情况下,r
是未初始化的存储指针,它导致变量指向存储槽 0。当您在结构 (r.state = 100;
) 中设置一些变量时,它将写入该值到插槽 0,其中 覆盖 _var
处的值。
当你想创建一个新的结构作为局部变量时,你想使用memory
修饰符,然后将其设置为状态变量(或将其添加到状态mapping/array) .当你想从 mapping/array 读取结构到局部变量时,使用 storage
.
对于您提供的示例,您想将其设置为 memory
变量。仔细阅读 Solidity 文档的 this section 。
Will the mutation work? Say, I read that a pure function cannot change state variables, and memory variables are copied. Is marking both as storage enough? Should I still declare pure for get_rand if it changes its argument?
不,它不会改变您的合同状态。虽然局部结构变量默认为 storage
,但函数参数默认始终为 memory
(即使是结构)。在 get_rand
中修改 rand
不会修改任何状态。如果您将函数更改为访问状态,您会因为 pure
修饰符而出现编译错误。