Working with structure arrays in solidity

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.

• 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, 2017 at 21:08

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.

• 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, 2016 at 15:26
• from what I understand this is perfectly possible using `push`, but not the other way around. Memory arrays have always a fixed length. Jul 19, 2016 at 15:33

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
}

``````