9

I have the following contract code example:

contract C {

    struct A {
        uint256 a;
        uint256 b;
    }

    struct B {
        A ax;
        uint256 c;
    }

    struct C {
        string name;
        B[] bs;
    }

    function init() {
        C memory c;
        B memory b;
        A memory a;

        a.a = 10;
        a.b = 20;

        b.ax = a;
        b.c = 30;

        c.name = "Test test test";
        c.bs[0] = b;
    }
}

Why can't I use push for the last statement

 c.bs[0] = b;

:

c.bs.push(b);

It throws the following error:

Untitled:30:9: Error: Member "push" is not available in struct B memory[] memory outside of storage.
        c.bs.push(b);
        ^-------^

but bs is an array of structures.

  • 1
    Not completely related to the original question but to comment on Roland's comment: > Memory arrays have always a fixed length. Memory arrays can have variable length by initializing them with the new keyword. solidity.readthedocs.io/en/develop/types.html#arrays – atc Aug 16 '17 at 21:08
10

Push is available only on storage arrays, that is member/ state variables and not in memory arrays, that is local variables:

push: Dynamic storage arrays and bytes (not string) have a member function called push that can be used to append an element at the end of the array. The function returns the new length.

http://solidity.readthedocs.io/en/latest/types.html

| improve this answer | |
  • So it's not possible to initialize a struct that contains an array and is stored in memory and then later append it as an element to an array in storage? – Sebi Jul 19 '16 at 15:26
  • 2
    from what I understand this is perfectly possible using push, but not the other way around. Memory arrays have always a fixed length. – Roland Kofler Jul 19 '16 at 15:33
1

Explaining further what atc mentioned in their comment,

Fixed vs variable length

  • Memory arrays have fixed length, which means their length cannot be modified after it is initialized. Since push() appends a new element at the end of the array, it is not available for memory arrays.

  • Storage arrays, on the other hand, can have variable length. Yet, they're more expensive. Do you have to use storage arrays for your use case? Maybe not; keep reading.

Static vs dynamic length

  • Static-length arrays are initialized with a length defined at compile time, which is specified inside the array's square brackets. If you want to initialize them with a length that's not defined at compile time, you'll get an error:
function bar(uint baz) public {
    uint[7] memory foo1; // this is fine
    uint[7] storage foo2; // this is fine
    uint[baz] memory foo3; // this throws a compile-time error
    uint[baz] storage foo4; // this throws a compile-time error
}

As you can see, this applies for both memory and storage arrays.

  • Dynamic-length arrays are initialized with a length defined at runtime, which is specified by means of the new keyword and written inside parentheses after the array's square brackets:
function bar(uint baz) public {
    uint[] memory foo1 = new uint[](7); // this is fine
    uint[] storage foo2 = new uint[](7); // this is fine
    uint[] memory foo3 = new uint[](baz); // this is fine
    uint[] storage foo4 = new uint[](baz); // this is fine
}

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.