1

So the code is

struct A {
    uint8[] a;
}

I want to initialize A by A a = A([1,2,3]);. However, solc says that can't convert uint8[3] to uint8[].

In conclusion, I am looking for a way to convert fixed-length array to dynamic-sized array. (without recreating the array by push n times)

2

This works:

contract Test {
    struct A {
        uint8[] a;
    }
    A one;
    A[] many;

    function Test() {
        one.a = [1, 2, 3];

        many.length++;
        many[0].a = [1, 2, 3];
    }
}

As a side note, to show you the storage layout of an array, if you have this contract:

contract Test1 {
    uint8[3] a; // Fixed size
    function Test1() {
        a = [1, 2, 3];
    }
}

Then after deployment, you get the following:

> web3.eth.getStorageAt(test1Address, 0) // Slot 0
"0x0000000000000000000000000000000000000000000000000000000000030201"
                                                             ^^^^^^ 3 values here

See how the 3 values are packed right on slot 0.

On the other hand, if you have this contract:

contract Test2 {
    uint8[] a; // Dynamic size
    function Test2() {
        a = [1, 2, 3];
    }
}

Then after deployment, you get the following:

> web3.eth.getStorageAt(test2Address, 0)
"0x0000000000000000000000000000000000000000000000000000000000000003"
// That's the length of the array on slot 0
> var arrayLocation = web3.sha3("0x0000000000000000000000000000000000000000000000000000000000000000", { encoding: "hex" })
// That's 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 BTW
> web3.eth.getStorageAt(test2Address, arrayLocation)
"0x0000000000000000000000000000000000000000000000000000000000030201"

See how the 3 values are sent to a pseudo-random location.

More in Layout of State Variables in Storage

1

Not sure where string came up. When I tried it, it complained about int8[] to uint256[] so I fudged the struct to match uint8[]. Also notice that I defined the array length as 3 so we aren't trying to force a fixed length array into a dynamic length array.

contract test {

    struct A {
      uint8[3] a;
    }

    A a = A([1,2,3]); 

    function getb() returns(uint8[3] whatWeGot) {
        return a.a;
    }
}

Looking again at your headline question. If the goal is a dynamic length array that starts with three values, then I would initialize with push(). Maybe something like this:

contract Test {

    struct Struct {
      uint[] myArray;
    }

    Struct myStruct; 

    function Test()  {
        myStruct.myArray.push(1);
        myStruct.myArray.push(2);
        myStruct.myArray.push(3);
    }

    function getter(uint index) returns(uint value) {
        return myStruct.myArray[index];
    }

}

Because you mentioned "string", there are some important differences between bytes and strings for this sort of thing.

Hope it helps.

  • oops. thanks for your answer, string was a typo. And, yes, I am finding a way to convert fixed-length array to dynamic-sized array. Pushing elements is basically what I did in my contracts... But, it doesn't seem to be good to have... – Fries Jan 23 '17 at 9:37
  • I'm nearly certain it's not possible to convert between dynamic and fixed and that's the end of the story. Experience has taught me there's often a clever person who can find a way. This might be one of those times so I left it out of my "answer". What's the concern about push? – Rob Hitchens - B9lab Jan 23 '17 at 9:53
  • Using some inline assembly, you can turn a fixed-length array into a dynamic one, but it's more readable and not much less efficient to just push each new element on in turn. – Tjaden Hess Jan 23 '17 at 15:54

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.