0

I want to define an in-memory 2-dimensional array without fully hard-coding its shape. Let's say I want a 3xN matrix (and to explain ill also set its 0th element to [1, 2, 3]):

function makeArr (int n){
    int[3][n] memory arr;
    arr[0] = [1, 2, 3]
}

makeArr(1) will fail with the message Invalid array length, expected integer literal or constant expression.

I tried defining the array like this:

int[3][] memory arr;

But that also doesn't work, because the array isn't long enough: reverted with panic code 0x32 (Array accessed at an out-of-bounds or negative index)

This question has been asked before, however the answer doesn't seem to have been accepted: Creating a 2D in-memory array in Solidity.

In another similar question, the answers at the time said this simply isn't possible (3yrs old). Returning 2D array with dynamic sizes from a function

Is there an answer yet or a best practice work-around?

0

makeArr(1) will fail with the message Invalid array length, expected integer literal or constant expression.

It's exactly what the message says - you can only use a compile-time constant or a literal to define the length of the array. If you only know the size of the array at runtime, you must use a dynamically-sized one.

But that also doesn't work, because the array isn't long enough: reverted with panic code 0x32 (Array accessed at an out-of-bounds or negative index)

This is what you want. You just did not allocate any memory for your array so its size is zero. Also, your code has some other problems. This is the correct way to do it:

function makeArr(uint n) pure {
    int[3][] memory arr = new int[3][](n);
    arr[0] = [int(1), 2, 3];
}

The problems I mentioned:

  • The array size must be an unsigned integer. You can always convert convert int to uint but then you have to validate it to ensure it's not negative. You're better off just changing the type of n to uint.
  • For array literals the type is based on the smallest common type all elements can fit into. So for [1, 2, 3] the type is uint8[3]. You need int[3] for the assignment to work so an explicit conversion is needed.
4
  • Thanks Cameel. It was this syntax throwing me off, where the length is specified in the parentheses and the rest in the square bracket. Why doesn't Solidity go with int[3][n] memory arr = new int[3][n]; OR int[][] memory arr = new int[][](3, n);? Oct 10 '21 at 23:57
  • The syntax is new <type name>(<arguments>) which might be confusing at first if the type is a nested array due to the extra brackets but ultimately is a pretty logical choice. int[3][n] and int[][] are two completely different types so using them does not seem like an improvement to me. Especially if it was new int[][](3, n) what would be the allocation syntax for int[][]? The current syntax lets you distinguish between dynamically- and statically-sized arrays, which is what matters. They are not interchangeable.
    – cameel
    Oct 11 '21 at 1:34
  • Ok, thanks for explaining. Last Q: If I want an in-memory array to add elements to, but I don't know how many ahead of time, would I just define the length as a number higher than what I expect i'll need (because to use .push the array has to be a storage array)? Oct 11 '21 at 5:27
  • It depends on the size of the array. This is the simplest solution so if the array is small or if you need it in nearly all cases then it's a reasonable strategy. Memory is usually cheap compared to execution cost and the compiler never even frees memory by itself. But in cases when this overhead is unacceptable, you'd need to look into implementing some data structure or maybe doing some inline-assembly optimizations. Memory cost grows non-linearly and when you get on the order of hundreds of kilobytes it'll start being very costly. If it's on the order of a few kB, you don't have to worry.
    – cameel
    Oct 11 '21 at 9:20

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.