0

I'm trying to initialize an int matrix in C++, with user-inputted dimensions, with every element set to zero. I know there are some elegant ways to do that with a one-dimensional array so I was wondering if there are any similar ways to do it with a two-dimensional array without using for loops and iterating through every element.

I found a source that gave several different ways, including std::fill (I've modified the code so that the dimensions are read with cin):

#include <iostream>
using namespace std;

int main() {
  int x;
  cin >> x;
  int matrix[x][x];

  fill(*matrix, *matrix + x * 3, 0);

  for (int i = 0; i < x; i++) {
    for (int j = 0; j < 3; j++) {
      cout << matrix[i][j] << " ";
    }
    cout << endl;
  }
}

But why does this work, and why would the pointer to the matrix in the arguments for fill be necessary if it's not necessary for a one-dimensional array? That source said it was because matrixes in C++ are treated like one-dimensional arrays, which would make sense, but that is why I don't understand why the pointer is needed.


I don't know if this is relevant, but in case it can help, I've described my previous attempts below.

At first I thought I could initialize all elements to zero like in a one-dimensional array. For the matrix, this worked fine when the side lengths were not read with cin (i.e. when I declared the matrix as int matrix[3][3] = {{}}; as answered here) but when I tried getting the side lengths from cin I started getting errors.

This was my code:

#include <iostream>
using namespace std;

int main() {
  int x;
  cin >> x;
  int matrix[x][x] = {{}};

  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      cout << matrix[i][j] << " ";
    }
    cout << endl;
  }
}

And when I tried to compile it, it threw this error:

matrix_test.cpp:7:14: error: variable-sized object may not be initialized
  int matrix[x][x] = {{}};
             ^
1 error generated.
Gravitron
  • 21
  • 4
  • 1
    `int matrix[x][x];` is not legal in standard `c++` by the rules of the standard the variable `x` must be a compile time constant. Here is why VLAs are not part of the standard: https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard – drescherjm Jul 12 '19 at 22:28
  • *But why does this work,* -- This does not compile `cin >> x; int matrix[x][x];` with the compiler I'm using (Visual Studio 2019), so there is no way for it to work. – PaulMcKenzie Jul 12 '19 at 22:36
  • Suggestion: [Use something like this.](https://stackoverflow.com/a/2076668/4581301) By default it will zero all elements. If you want to change the default value, `Matrix::Matrix(size_t rows, size_t cols, double def) : mRows(rows), mCols(cols), mData(rows * cols, def) { }` – user4581301 Jul 12 '19 at 22:41
  • this answer should help you https://stackoverflow.com/a/56907315/10933809 – Oblivion Jul 12 '19 at 22:41
  • 1
    As for what went wrong, since the size is variable, the compiler is not able to generate initialization code to zero the array at compile time. It could generate code to do the initialization at run time, but what's the fun in doing that? – user4581301 Jul 12 '19 at 22:45
  • 1
    [An answer if you cannot use `std::vector`](https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048) – PaulMcKenzie Jul 12 '19 at 22:51
  • @PaulMcKenzie I'm using the GCC compiler, version 4.2.1, from the terminal — not sure if that makes a difference, but for some reason the code works for me. And thank you to everybody for all the helpful resources! – Gravitron Jul 13 '19 at 00:11
  • 1
    Unrelated: GCC 4.2.1, wowzers. That's almost as bad as the GCC 3.3.1 I need to use for a few legacy projects from the early 2000s. I assume you're stuck with that moldy old and can't upgrade to something a decade newer? – user4581301 Jul 13 '19 at 00:17
  • Uh, no, sorry, I'm just a beginner and didn't know anything better. It just came pre-installed on my computer and that's all I ever learned. Thanks for letting me know I could do with something better. – Gravitron Jul 13 '19 at 00:20
  • 1
    Not knowing what your computer is, I can't make good suggestions on how to upgrade GCC. In Linux, it could be a matter of asking the package manager for GCC 8 or 9. In Windows [follow along with this](https://stackoverflow.com/a/30071634/4581301). On a Mac... That's one damn old Mac. I dunno how you'd update it. – user4581301 Jul 13 '19 at 05:22
  • It's a mac, unfortunately. Thanks for the help anyways. – Gravitron Jul 13 '19 at 16:01

2 Answers2

0

Why you're getting the error

c-style arrays (such as int matrix[3][3]) must have size specified at the point you declare it. They can't vary in size in C++.

What you could do instead.

If you use std::vector, there's a really elegant way to do it:

#include <vector>
#include <iostream>

int main() {
    using namespace std; 

    int x;
    cin >> x;

    auto matrix = vector<vector<int>>(x, vector<int>(x, 0)); 

    // This is how we can print it
    for(auto& row : matrix) {
        for(auto& elem : row) {
            cout << elem << ' '; 
        }
        cout << '\n'; 
    }
}

In C++17, you can shorten this even further:

    auto matrix = vector(x, vector(x, 0)); 

What vector(number, thing) means is "Create a vector of number, where each element is thing".

Alecto Irene Perez
  • 10,321
  • 23
  • 46
  • Not quite true. The compiler the Asker is using does allow variable length arrays, but it does not allow you to initialize a variable length array. – user4581301 Jul 12 '19 at 23:13
0

The second dimension of two-dimension array must be a compile time constant, but in your code x is not.

Actually if you write a function with a two-dimension parameter, the second dimension must also be a compile time constant. That's because the array is stored linearly in the memory and the compiler must know the second dimension to calculate the offset correctly.

jerry_fuyi
  • 483
  • 4
  • 12