我阅读了一些关于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)我应该在storage
中为memory
或main
标记本地变量吗?我应该在get_rand
?
2)突变是否有效?说,我读到pure
函数不能更改状态变量,并且复制了内存变量。是否标记为storage
足够?如果pure
更改其参数,我是否还应声明get_rand
?
由于
答案 0 :(得分:0)
状态变量是永久存储在合同存储中的值。它们在合同范围内和外部功能范围内声明。像这样:
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
因此合同的整体层次结构如下:
Contract
--/ State Variables
--/ Functions
除此之外,我无法理解你的要求。也许你应该在单独的问题中清楚地问清楚,而不是在一个问题中模糊地问他们。
答案 1 :(得分:0)
view
和pure
是函数修饰符,用于描述该函数中的逻辑如何与契约状态交互。如果您的合同将从存储中读取,但不是写入,则您将使用view
(或constant
完全相同的)修饰符(请参阅view functions documentation)。如果您不打算从合同状态读取或写入,并且您所做的一切只适用于内存变量,则它是pure function。
我应该在main中为本地变量标记存储空间还是内存?我应该在get_rand中为参数标记什么?
默认情况下,结构是storage
变量,它会尝试将结构写入状态。这是您需要小心的地方,因为如果您使用storage
变量,您实际上可以覆盖您的状态,您应该使用memory
。例如:
contract C {
uint _var;
function f() public {
Random r;
...
}
}
在这种情况下,r
是未初始化的存储指针,它使变量指向存储槽0.当你在struct(r.state = 100;
)中设置一些变量时,它会将该值写入槽0 覆盖 _var
处的值。
如果要将新结构创建为局部变量,则需要使用memory
修饰符,然后将其设置为状态变量(或将其添加到状态映射/数组)。如果要将映射/数组中的结构读取到局部变量中,请使用storage
。
使用您提供的示例,您希望将其设置为memory
变量。请仔细阅读Solidity docs very 的this section。
突变是否有效?说,我读到一个纯函数不能改变状态变量,并且复制了内存变量。是否足够标记存储?如果它改变了参数,我还应该为get_rand声明pure吗?
不,它不会改变合同的状态。虽然本地结构变量默认为storage
,但默认情况下函数参数始终为memory
(甚至是结构)。在rand
内修改get_rand
不会修改任何州。如果您将函数更改为访问状态,则由于pure
修饰符而导致编译错误。