0

I am trying to pass a dynamic 2-D array to a function and it gives an error. I tried explicitly providing the array dimensions and it worked but dynamic is not working, any pointers (pun not intended)

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, int (*arr)[5]){
    for(int i = 0; i < arr_size; ++i){
        for(int j = 0; j < arr_size; ++j)
            cout << arr[i][j] << "\t";
        cout << endl;
    }
}

int main(){
    vector<int> x{10,15,20,30,40};
    int arr[x.size()][x.size()];

    for(int i = 0; i < x.size(); ++i)
        arr[i][i] = 0;

    print_2d_array(5, arr);
    return 0;
}

I tried all the three methods that were detailed here Passing 2D array in C

If instead of instantiating the array as shown above, I use something like

arr[5][5];

it works as expected. I am getting the following error

error: cannot convert ‘int (*)[(<anonymous> + 1)]’ to ‘int (*)[5]’ for argument ‘2’ 
to ‘void print_2d_array(int, int (*)[5])’

print_2d_array(5, arr);

Community
  • 1
  • 1
Rahul Kadukar
  • 790
  • 3
  • 12
  • 31
  • You are already using a vector, why not use a vector of vectors as a 2d array? Save yourself the trouble. – Neil Kirk Apr 13 '15 at 04:20
  • Yes, that is how I am going ahead at this time, but I wanted to know the way to do it without using vector of vectors. – Rahul Kadukar Apr 13 '15 at 04:35

2 Answers2

1

Variable Length Array (VLA) is not part of C++ standard. It is part of C99 standard, and typically implemented as an extension for C++ in various compilers.

It is typically ok to use a VLA in a C++ program when you allocates an array. But you are going to have problems when you need to pass the array around, because there is no argument type that is VLA so that you can pass it as arguments to functions in C++. (That's why when you manually inline the function, the code runs ok, which avoids passing the array into a function.) You have to pass the array as a pointer to the function, and maybe use reinterpret_cast before and inside the function to convert the VLA to a pointer, and convert it back. It is simply terrible code.

When coding in C++, just use the C++ idiomatic way. Since you already use vector, you can just use vector<vector<int>> (vector<vector<int> > if not using C++11, but from the way you initialize x, you are using C++11) as a 2-D array. Your code should be modified as below:

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, vector<vector<int>> &arr){
    for(int i = 0; i < arr_size; ++i){
        for(int j = 0; j < arr_size; ++j)
            cout << arr[i][j] << "\t";
        cout << endl;
    }
}

int main(){
    vector<int> x{10,15,20,30,40};
    vector<vector<int>> arr(x.size(), vector<int>(x.size()));

    // No need to use this to initialize:
    // for(int i = 0; i < sizeof(x); ++i)
    //     arr[i][i] = 0;

    print_2d_array(5, arr);
    return 0;
}

Note that this also fixed your problem that your arr was not properly initialized.

If you are going to use C, then VLA is totally ok, and it will be like this (and not that I didn't fix your initialization, which only initialized the diagonal elements. You have to use a C, not C++ compiler to compile this.):

#include <stdio.h>

void print_2d_array(int arr_size, int arr[][arr_size]){
    for(int i = 0; i < arr_size; ++i){
        for(int j = 0; j < arr_size; ++j)
            printf("%d\t", arr[i][j]);
        printf("\n");
    }
}

int main(){
    int x[] = {10,15,20,30,40};
    int arr[sizeof(x)][sizeof(x)];

    // bad initialization:
    for(int i = 0; i < sizeof(x); ++i)
        arr[i][i] = 0;

    print_2d_array(5, arr);
    return 0;
}

Ok, if you decide to use C++ but don't like vector, the next simplest thing is to use primitive pointers, which is not recommended.

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, int **arr){
    for(int i = 0; i < arr_size; ++i){
        for(int j = 0; j < arr_size; ++j)
            cout << arr[i][j] << "\t";
        cout << endl;
    }
}

int main(){
    vector<int> x {10,15,20,30,40};
    int **arr = new int*[x.size()];
    for (int i = 0; i < x.size(); ++i) {
        arr[i] = new int[x.size()];
        for (int j = 0; j < x.size(); ++j) {
            arr[i][j] = 0;
        }
    }

    print_2d_array(5, arr);

    for (int i = 0; i < x.size(); ++i) {
        delete[] arr[i];
    }
    return 0;
}

Save your trouble and use containers. You are using modern C++.

(The answer assumes you couldn't determine the size of the array before running. Although this is not the case in your example--the size must be 5 and there is no reason to use VLA.)

Canautumn
  • 26
  • 2
0

First of all,

int arr[x.size()][x.size()];

is not valid C++. The dimensions of array must be known at compile time.

If you use a compiler that supports variable length arrays as an extension, you can use that statement. But then, the type of the variable is not int (*)[5], which is what is expected by print_2d_array.

You can use a nested std::array if you know the dimensions at compile time.

You can use a nested std::vector if need to compute the dimensions at run time.

Update, in response to OP's comment

Take a simplified version of the program.

#include <iostream>
#include <vector>

using namespace std;

int main(){
    vector<int> x{10,15,20,30,40};
    int arr[x.size()][x.size()];
    return 0;
}

Command to compile:

g++ -Wall -std=c++11    socc.cc   -o socc -pedantic

Errors/warnings:

socc.cc: In function ‘int main()’:
socc.cc:8:31: warning: ISO C++ forbids variable length array ‘arr’ [-Wvla]
     int arr[x.size()][x.size()];
                               ^
socc.cc:8:31: warning: ISO C++ forbids variable length array ‘arr’ [-Wvla]
socc.cc:8:9: warning: unused variable ‘arr’ [-Wunused-variable]
     int arr[x.size()][x.size()
R Sahu
  • 196,807
  • 13
  • 136
  • 247
  • I want to understand what you mean by not valid C++. If I write the exact same code as above and do the function processing inline, it works as expected. Here is a sample http://ideone.com/S285pA – Rahul Kadukar Apr 13 '15 at 04:29