7

A struct which contains a dynamic arrays seems to be impossible to initialize, e.g. this doesn't work:

contract Quux {
    struct Foo {   string[] bar;     }
    mapping (address => Foo) foos;
    function Quux() { 
        foos[msg.sender] = Foo([]);
    }
}

It looks like it's impossible to say "I just want an empty array here".

This isn't specific to structs, though, the following won't work either:

 mapping (address => uint[]) foos;
 ...
 foos[msg.sender] = [];

A possible workaround is to access "non-existent" structure, e.g.

    function Quux() { 
        Foo myFoo = foos[msg.sender];
        myFoo.bar.push("xxx");
    }

Is this how it's supposed to work?

1 Answer 1

13

You can proceed on the understanding that struct vals and dynamic arrays are initialized.

Mappings can be thought of as namespaces with all possible keys initialized to zero values. In other words, for every possible address, there's a struct, and it's member values contain 0, false, null, or in the case of a dynamic array, length 0.

This little contract let's one set and get to a dynamic array tied to the msg.sender. You'll see the dynamic array length is initialized to 0. Note that at the outset, you can't access row[0] (via getStringAtIndex()) because the array is empty. Throws a JUMP because the first row is past the end.

As I put this together, I thought about passing in addresses instead of using msg.sender. Doing so would let you explore the 'unset' structs in the mapping. Nothing will go wrong if you access an uninitialized location; you'll just get a zeroed out struct containing a zero-length. Leaving it this way to more closely relate to your original code. In practice, msg.sender is the right way to go for a lot of use-cases.

pragma solidity ^0.4.6;

contract Zero {

  struct MyStruct {
    string[] structArray;
  }

  mapping(address => MyStruct) myStructs;

  function Zero() {
    // nothing to do
  }

  function appendString(string appendMe) returns(uint length) {
    return myStructs[msg.sender].structArray.push(appendMe);
  }

  function getCount() constant returns(uint length) {
    return myStructs[msg.sender].structArray.length;
  }

  function getStringAtIndex(uint index) constant returns(string value) {
    return myStructs[msg.sender].structArray[index];
  }
}

And here is Browser Solidity showing it works:

enter image description here

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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