1

I'm looking to define a 2 dimensional character array where arguments I pass to a function holding the array will be used to determine the size each dimension of the array.

int func(const int x, const int y) {

    char maze[x][y] = { 0 };
    return 0; 
}

When defining x & y inside the function as constant integers the array is defined just fine. When x and y are arguments to the function the program won't compile. Why is this and how do I get around it?

  • This is not legal in standard `c++`. Both `x` and `y` need to be compile time constants not function parameters. – drescherjm Dec 18 '18 at 16:30
  • 3
    Since the size is not a compile-time constant, you need a dynamic array. `std::vector` in other words. – super Dec 18 '18 at 16:31
  • 2
    Use `std::vector maze(x * y);`. Then, instead of `maze[pos_y][pos_x]` use it like this: `maze[pos_x + pos_y * x]`. – HolyBlackCat Dec 18 '18 at 16:32
  • you can use template for `x` and `y` but I don't think it is what you are looking for – Damien Dec 18 '18 at 16:35
  • 2
    Some reading: [Why aren't variable-length arrays part of the C++ standard?](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – user4581301 Dec 18 '18 at 16:44

3 Answers3

2

You can make a wrapper around 1-dimensial array like this:

class Maze {
    friend class Row;
public:
    /* This helper class represents a single row of the maze */
    class Row {
        friend class Maze;
        Maze& owner;
        std::size_t row;
        Row(Maze& owner_, std::size_t row_) : owner(owner_), row(row_) {}
        /* this operator resolves 2nd pair of brackets */
    public:
        inline char& operator[](std::size_t col) { return owner.data[col + row*owner.cols]; }
    };
    Maze(std::size_t rows_, std::size_t cols_)
      : data(rows_ * cols_, 0)
      , cols(cols_)
    {}
    /* this operator resolves 1st pair of brackets */
    inline Row operator[](std::size_t index) { return Row(*this, index); }
private:
    std::vector<char> data;
    std::size_t cols;
};

...

Maze m(5, 10);
m[2][3] = 1;
  • 1
    `operator[]` could return a pointer to the start of the row (`return data.data() + index * cols;`), so you don't need the inner class. – Artyer Dec 18 '18 at 18:19
0

You need to use dynamic memory allocation. Variadic length arrays is not a part of c++ standart. However variadic length arrays available as an extension for GCC. Although you can use STL or implement your class, dont forget about new[] and the one-dimensional representation for two-dimensional array:

char* maze = new char[x*y]; // create
maze[i + j * x]; // access
delete[] maze; // delete

It is compact and in most cases fast.

Dmytro Dadyka
  • 2,208
  • 5
  • 18
  • 31
0

When defining x & y inside the function as constant integers the array is defined just fine

It works because the size of your array is defined and known by your compiler, known at compile-time

When x and y are arguments to the function the program won't compile.

When you wish to define you array only when you call your function, you ask your program to do that during runtime . As answered by Dmytro Dadyka, you have to use use dynamic memory allocation and manage yourself memory deallocation (delete[] maze; // delete)

Here is an alternative of defining dynamically your 2D array using template! Notice that it is always done at compile-time.

template<int X, int Y>
int f()
{
    char c[X][Y];

    for(int x=0; x < X; ++x)
    {
        for(int y=0; y < Y; ++y)
        {
            c[x][y] = '1';
        }


    }
    // write your algorithm now!....
    c[2][2] = 'a';

    for(int x=0; x < X; ++x)
    {
        for(int y=0; y < Y; ++y)
        {
           std::cout << c[x][y] << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}

    int main()
    {
      f<5,5>();
      f<7,4>();
      return 0;
    }
Ratah
  • 299
  • 3
  • 11