Hi,

I have code as follows wherein I pass a 2D array to a function and want to receive this array with its contents tripled.

#include <iostream>
#include <cstdio>
using namespace std;

int** test2 (int arr2[][4],int mul){
	for (int i=0;i<2;i++){
		for(int j=0;j<4;j++){
		arr2[i][j]=arr2[i][j]*mul;
	    }
	}
	return arr2;//sending back the address location
}


int main(){

// code to pass and receive a 2d array
    int arr2d[][4]=	{{1,2,1,1},{2,2,3,4}};
    int** ptrarr2d=test2(arr2d,3); 
    cout << ptrarr2d[0][1] << " " << ptrarr2d[0][1]<< " "<< ptrarr2d[0][2] << " " <<    ptrarr2d[0][3]; // to print 1st row in arr2d

    return 0;
}

The error I get is 'error: cannot convert 'int (*)[4]' to 'int**' in return'.
I was able to send and receive a 1D array using 'pass by value' but for 2D I hit this error. Please advice.

Edited 6 Years Ago by Nick Evan: Replaced icode-tags with code-tags. ICODE is meant for 1 line only. Please use CODE for blocks

You could typecast your return type to explicitly return an int**, which would make it compile, but it still wouldn't run right. I'm guessing that you int** does not dereference correctly from a 2-D array to a 1-D array. arr2d may know it's a 2-d array and thus **arr2d and *arr2d point to the same address, but ptr2darr doesn't and thus it doesn't dereference properly. It is in fact a pointer to the first element of the 2-d array, not the first row. So you can't dereference it twice like you can with arr2d.

So you'll need to do something a bit more involved to get it to work. Decide whether you even need/want that second pointer. You still have your original pointer and you can make it a void function.

#include <iostream>
#include <cstdio>

using namespace std;

int** test2 (int arr2[][4],int mul){
	for (int i=0;i<2;i++){
		for(int j=0;j<4;j++){
		arr2[i][j]=arr2[i][j]*mul;
	    }
	}

	return (int**) arr2; // compiles but poses problems
}


int main(){

// code to pass and receive a 2d array
    int arr2d[][4]=	{{1,2,1,1},{2,2,3,4}};
    int** ptrarr2d = test2(arr2d,3);

    cout << arr2d << "\t" << *arr2d << "\t" << **arr2d << endl;
    cout << ptrarr2d << "\t" << *ptrarr2d << "\t" << **ptrarr2d << endl;// crashes

    cout << arr2d[0][0]<< " " << arr2d[0][1]<< " "<< arr2d[0][2] << " " <<    arr2d[0][3]; // works fine

    return 0;
}

Here's a semi-similar thread I posted a while ago that may be of interest.

http://www.daniweb.com/forums/thread127068.html

There are 2 solutions to your problem. First which I believe is the more simpler one. Here you are dealing with a single pointer which points to the beginning of the array

int* test2 (int arr2[][4],int mul){
	for (int i=0;i<2;i++){
		for(int j=0;j<4;j++){
		arr2[i][j]=arr2[i][j]*mul;
	    }
	}
	return &arr2[0][0];//sending back the address location
}

int main(void)
{
    int arr2d[][4]= {{1,2,1,1},{2,2,3,4}};
    int* ptrarr2d=test2(arr2d,3);
    for(int i=0;i<4;i++)
      cout<<*(ptrarr2d +i)<<" ";
    
    cout<<endl;
    cin.get();
    return 0;
}

Here is the second solution. This is more closer to your approach. Here we use a pointer to array. Notice how the function has been declared.

int (*test2 (int arr2[][4],int mul))[4]
{
	for (int i=0;i<2;i++){
		for(int j=0;j<4;j++){
		arr2[i][j]=arr2[i][j]*mul;
	    }
	}
	return arr2;
}


int main(void)
{
    int arr2d[][4]= {{1,2,1,1},{2,2,3,4}};
    int (*ptrarr2d)[4] =test2(arr2d,3);
    
    int* p;
    p= (int*)ptrarr2d;
    
    for(int i=0;i<4;i++)
       printf ("%d ",*(p+i));
       
    printf("\n");
    
 //   for(int i=0;i<4;i++)
 //     cout<<*(ptrarr2d +i)<<" ";
    
    cout<<endl;
    cin.get();
    return 0;
}

Edited 6 Years Ago by abhimanipal: n/a

Hi,

I have code as follows wherein I pass a 2D array to a function and want to receive this array with its contents tripled.

The error I get is 'error: cannot convert 'int (*)[4]' to 'int**' in return'.
I was able to send and receive a 1D array using 'pass by value' but for 2D I hit this error. Please advice.

The most obvious solution is to not return anything from the function. Since the array is passed to the triple function by reference, there is no need to return its address. You can simply pass the array to the function, modify it in place in the function, and when the function returns, the array will have been modified and its address will be the same. There is absolutely no need to return a pointer from the function. For example:

#include <iostream>
using namespace std;

int* modify( int arr[4] )
{
    for( int i=0; i<4; i++ )
        arr[i] += 1;
    return (int*)(arr);
}

int main()
{
    int origArr[4];
    memset( origArr, 0, 4 * sizeof(int) );  // fill with 0's
    int* newPtr = modify( origArr );  // Now it is filled with 1's
    cout << ( newPtr == origArr ) << endl;  // The pointer references the same location as the original array
    return 0;
}

You could instead simply do this:

#include <iostream>
using namespace std;

void modify( int arr[4] )
{
    for( int i=0; i<4; i++ )
        arr[i] += 1;
}

int main()
{
    int origArr[4];
    memset( origArr, 0, 4 * sizeof(int) );  // fill with 0's
    for( int i=0; i<4; i++ )
        cout << origArr[i] << " ";
    cout << endl;
    modify( origArr );  // Now it is filled with 1's
    for( int i=0; i<4; i++ )
        cout << origArr[i] << " ";
    cout << endl;
    return 0;
}

output:

0 0 0 0 
1 1 1 1

Finally, I disagree with ever passing an array with a fixed size to a function. If your function is operating on an array, it should also be informed of the dimensions. This allows better extensibility and readability. I would recommend you write multi-dimensional array manipulation functions like so:

void modify( int** arr, int w, int h /* additional arguments here */ )
{
    for( int i=0; i<h; i++ )
        for( int j=0; j<w; j++ )
            // do something to arr[i][j]
}

The real key here is to understand that arrays are always passed by reference, so if you are planning to modify them in place, you never need to return the array pointer/reference.

Dear all,

Thank you for the advice on this topic. I managed to play around with 2D arrays and pass them by reference. Things look alright now. I did not realise that arrays are passed by reference 'always' and thus went behind pointers :)
I have just started coding in C++ so I am sure to hit more doubts but it is a nice start.

This question has already been answered. Start a new discussion instead.