2

I searched and found 'how to use 2d array as parameter in c/c++' but I encountered weird thing.

void print2darr3 (int row, int column, int **arr){
    int i,j;
    for( i = 0; i<row ;i++ ){
            for( j=0 ; j<column ;j++ ){
                printf("%d ", **(arr++))  ;    //printf("%d ", *(arr++)); WORKS WELL.
            }
            printf("\n");
    }
}

int main(void){
   int arr[3][3] = {
                        {10,20,30},
                        {40,50,60},
                        {70,80,90}
                    };

    print2darr3(3,3, arr);
return 0;
}

This is what I wrote. I intended the output like this

10 20 30

40 50 60

70 80 90

But my code doesn't work.

Surprisingly, when I changed my code printf("%d ", * (arr++)); instead of printf("%d ", ** (arr++)); at line 5, it works well.

I can't understand this situation.

Because arr[3][3] is 2-dimensional array, I wrote int **arr as a parameter.

Thus I used printf("%d ", **(arr++)) to print out each element.

Why only one * works well in this code? rather than **?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Emptyset0
  • 23
  • 2

4 Answers4

4

Arrays passed as function arguments do not adjust to pointers beyond the first dimension. You would need to change the function header to :

void print2darr3 (int col, int *arr[3]); // removed row because it is known to be 3.

If you want the function to be more general and work for pointer-to-pointer-to-int (or int**) types, you would need to create the array dynamically. This is done with malloc()/free() in C and new/delete in C++. Technically, you could use malloc() in C++, but this is strongly discouraged.

Here's an example (for C, not C++):

int 
    nrows = 3, 
    ncols = 3;

int **arr = malloc(nrows * sizeof(int*));
int i;

for(i = 0; i < nrows; ++i) {
    arr[i] = malloc(ncols * sizeof(int));
}

// now you can use the arr as a 2D array in your original function

print2darr3(nrows, ncols, arr);

EDIT

As @Neil pointed out in the comments, it's important to free memory you've allocated with malloc(). Otherwise, you would create a memory leak. In order to do that, you use free().

for(i = 0; i < nrows; ++i) {
    free(arr[i]);
}

free(arr);

Note

The reason why I answered for C is because it seemed to me like that's what you were using. In C++, this use of malloc() will not work, as you would need an explicit cast there, and there is no such language as C/C++, they are nearly compatible, but not completely compatible.

Nasser Al-Shawwa
  • 3,573
  • 17
  • 27
2

C++ solution (which you tagged)

void print2darr3 (const vector<vector<int>>& arr){
    int i,j;
    for( i = 0; i<arr.size() ;i++ ){
            for( j=0 ; j<arr[i].size() ;j++ ){
                printf("%d ", arr[i][j]) 
            }
            printf("\n");
    }
}

int main(void){
vector<vector<int>> arr = {
                    {10,20,30},
                    {40,50,60},
                    {70,80,90}
                };

print2darr3(arr);
}
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • 2
    While that does solve the problem, that doesn't explain why OP's code wasn't working. Maybe you want to explain that? – Borgleader Jul 20 '14 at 14:45
1

If you have an array

int arr[3][3];

passing it to a function means the first dimension "decays" to a pointer. It is only the first dimension that decays, so instead of int **arr (a pointer to a pointer, or an array of pointers) as a parameter, you want int (*arr)[3] (a pointer to an array of 3 elements, or an array of arrays, each of which contain 3 elements).

You can read more elsewhere (I have a lengthy answer here that describes more, and Question 6.18 of the comp.lang.c FAQ is even better), but it is important to understand the difference between arrays-of-arrays/pointers-to-arrays and arrays-of-pointers/pointers-to-pointers.

Community
  • 1
  • 1
0

Arrays are not pointers!

They just happen to be automatically demoted to a pointer to the first element.


For example, if we have int arr[2], then arr represents two consecutive ints in memory, and it gets demoted to a pointer to the first element (so it has type int*):

         arr ---+        +--- arr + 1
                v        v
memory: ... | arr[0] | arr[1] | ...


But if we have int arr[2][2], then arr represents four consecutive ints in memory, and it gets demoted to a pointer to the first element (so it has type int (*)[2]):

           arr ---+            arr + 1 ---+
                  v                       v
memory: ... | arr[0][0] | arr[0][1] | arr[1][0] | arr[1][1] | ...


If, on the other hand, we have int *(arr[2]) (parentheses added for clarity), then arr represents an array of two consecutive int pointers in memory, and it gets demoted to a pointer to the first element (so it has type int**):

         arr ---+        +--- arr + 1
                v        v
memory: ... | arr[0] | arr[1] | ...
                |        |     
           ... -+        +- ...



In your case, print2darr3 expects something like the third example, but you are giving it something like the second.

You can go either way:

#include <stdio.h>

void print2darr3(int rows, int columns, int *arr) {

    int i,j;

    for (i = 0; i < rows ; i++) {
        for (j = 0; j < columns; j++) {
            printf("%d ", arr[i * columns + j]);
        }
        printf("\n");
    }
}

int main(void) {

    int linear_array[3][3] = {
        {10,20,30},
        {40,50,60},
        {70,80,90},
    };

    print2darr3(3, 3, (int*)linear_array);
    return 0;
}


Or:

#include <stdio.h>

void print2darr3(int rows, int columns, int **arr) {

    int i,j;

    for (i = 0; i < rows ; i++) {
        for (j = 0; j < columns; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

int main(void) {

    int linear_array[3][3] = {
        {10,20,30},
        {40,50,60},
        {70,80,90},
    };

    int *pointer_array[3] = {
        (int*)(linear_array + 0),
        (int*)(linear_array + 1),
        (int*)(linear_array + 2),
    };

    print2darr3(3, 3, pointer_array);
    return 0;
}


Also, in C (but not in C++) you can do:

#include <stdio.h>

void print2darr3(int rows, int columns, int arr[rows][columns]) {

    int i,j;

    for (i = 0; i < rows ; i++) {
        for (j = 0; j < columns; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

int main(void) {

    int linear_array[3][3] = {
        {10,20,30},
        {40,50,60},
        {70,80,90},
    };

    print2darr3(3, 3, linear_array);
    return 0;
}
esneider
  • 589
  • 4
  • 12