6

I have a 2 dimensional array dynamically allocated in my C code, in my function main. I need to pass this 2D array to a function. Since the columns and rows of the array are run time variables, I know that one way to pass it is :

-Pass the rows and column variables and the pointer to that [0][0] element of the array

myfunc(&arr[0][0],rows,cols)

then in the called function, access it as a 'flattened out' 1D array like:

ptr[i*cols+j]

But I don't want to do it that way, because that would mean a lot of change in code, since earlier, the 2D array passed to this function was statically allocated with its dimensions known at compile time.

So, how can I pass a 2D array to a function and still be able to use it as a 2D array with 2 indexes like the following?

arr[i][j].

6 Answers 6

6

See the code below. After passing the 2d array base location as a double pointer to myfunc(), you can then access any particular element in the array by index, with s[i][j].

#include <stdio.h>
#include <stdlib.h>

void myfunc(int ** s, int row, int col) 
{
    for(int i=0; i<row; i++) {
        for(int j=0; j<col; j++)
            printf("%d ", s[i][j]);
        printf("\n");
    }
}

int main(void)
{
    int row=10, col=10;
    int ** c = (int**)malloc(sizeof(int*)*row);
    for(int i=0; i<row; i++)
        *(c+i) = (int*)malloc(sizeof(int)*col);
    for(int i=0; i<row; i++)
        for(int j=0; j<col; j++)
            c[i][j]=i*j;
    myfunc(c,row,col);
    for (i=0; i<row; i++) {
        free(c[i]);
    }
    free(c);
    return 0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is it - albeit the code has slight errors in the mem. alloc part.. but got the gist.
3

If your compiler supports C99 variable-length-arrays (eg. GCC) then you can declare a function like so:

int foo(int cols, int rows, int a[][cols])
{
    /* ... */
}

You would also use a pointer to a VLA type in the calling code:

int (*a)[cols] = calloc(rows, sizeof *a);
/* ... */
foo(cols, rows, a);

Comments

1

As far as I know, all you can pass to a function is a pointer to the first element of an array. When you pass an actual array to a function, it is said that "the array decays into a pointer" so no information about the size(s) of the pointed array remains.

A reference to an object of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T.

I believe you will be able to find more information about this on the C FAQ.

1 Comment

This answer was true before year 1999. You can use a pointer to VLA, even without the pointed-at array being a VLA. You only lose the size information of the inner-most array. Or if you don't want that, you can use a pointer: func(size_t x, size_t y, int (*arr)[x][y]).
0

You really can't do this without changing a lot of code. I suggest to wrap this in a structure which contains the limits and then use regexp search'n'replace to fix the accesses.

Maybe use a macro like AA(arr,i,j) (as in Array Access) where arr is the structure.

2 Comments

So basically u are saying - no programatic way to get it done, but 'search and replace'. Is it correct?
Just changing the function declaration/definition wouldn't be "changing a lot of code".
0

I think this to be the easiest way. Very similar to double array[m][n] - but dynamicly allocated:

#include <stdio.h>
#include <stdlib.h>

void print(double *arr, int m, int n)                    // First transfer the number of the rows. Then the number of the columns.
{
    int i, j;
    
    for (i = 0; i < m; i++) {                           // Count the rows.
      for (j = 0; j < n; j++) {                         // Count the columns.

        // printf("%d ", *((arr+i*n) + j));             // Do not use this kind of writing: seems to work with integers.
                                                        // Please write the code as follows:
        printf("%fd ", *((double *)arr+(i*n) + j));     // Herbert Schildt - published by Osborne page 103 : 
                                                        // It is most important to declare the "base-type" of the values.
      }
      printf("\n");
    }
}

void write_any_values_to_double_array(double *arr, int m, int n)
{
    int i, j, count;
    double any_value = 240.465;

    for (i = 0; i < m; i++) {                           // Count the rows.
      for (j = 0; j < n; j++) {                         // Count the columns.
       
       *((double *)arr+(i*n) + j) = any_value;
       any_value += 1.0;
      }
    }
}  // end of function


int main()
{
    //int arr[][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, {16, 17, 18, 19, 20}};
    // Problem: In C - in contrast to C++ - you have to define the size of one dimension of the array. 
    // Also when you transfer the array to a funktion. ->  void function(double array[][5], ......);
   
   int m = 4, n = 5;      // Define the number of the rows first, then the number of the columns.

   double* tri;                                        // Create a pointer.
   
   // Dynamically allocate memory using calloc()
   tri = (double*)calloc((m) * n, sizeof(double));     // Then create some space for the values.   Similar to: tri[m][n]   Call  free(tri); later! 
                                                       // The function calloc() is similar to malloc(). 
                                                       // But all the elements are initiatized to 0.   
   print(tri, m, n);  
   write_any_values_to_double_array(tri,  m,  n);
   print(tri, m, n); 

   *((double*)tri + (1 * n) + 3) = 3.14152864;         // Secound row, 4. column
   print(tri, m, n);

   free(tri);

   return 0;
}

5 Comments

Why do you think this is easier than this answer? stackoverflow.com/a/3420526/584518
I wrote it above the code. Who wants to think double array ** ...?
The link I referred to doesn't use ** which would be wrong since a pointer to pointer cannot point at an array. It's much cleaner and easier to use arr[i][j] syntax when accessing an actual 2D array IMO. What you propose here are "mangled arrays" which is how it was done in the 1990s.
To clarify: don't you think this cleaned up version of your code is way clearer? godbolt.org/z/vTss8r75c
Dear Ludin, your code is just the best - and shows in a very easy readable way what the code above is also doing. I recomend everyone to view your code first. But to define an arraysize by a variable is only possible with a most modern compiler. In my experiance not available for most microcontrollers.
-3

A 2-d array in C is just an array of arrays. Here ya go:

void with_matrix(int **matrix, int rows, int cols) {
    int some_value = matrix[2][4];
}

int main(int argc, char **argv) {
    int **matrix;
    ... create matrix ...
    with_matrix(matrix, rows, cols);
}

1 Comment

"A 2-d array in C is just an array of arrays" Yes. Your code does however not contain any arrays...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.