# Thread: regarding passing 2d array to functions

1. ## regarding passing 2d array to functions

Hi all,

I have a general question.

This is regarding better understanding of representation/usage of 2D arrays.
consider the following.

Code:
```#define MAX_COLS 4

int **first_array;
int second_array[][MAX_COLS];```
Above, I have declared (defined) two 2D arrays namely first_array, and second_array.

Now, imagine there is a function that takes as an argument a 2D array.
Code:
```void print_2D_array(int an_array[][MAX_COLS], int num_rows) {
for (int x = 0; x < num_rows; x++) {
for (int y = 0; y < MAX_COLS; y++) {
printf(" %d ", an_array[x][y]);
}
printf("\n");
}
printf("\n");
}```
Now, what is the correct way to pass "first_array" and "second_array" to the function "print_2D_array".

In my application, I am doing the following to get correct outputs.
Code:
```print_2D_array(&first_array[0][0], num_rows);
print_2D_array(second_array, num_rows);

// another example
int m_hierarchy[13][4]; // part of structure
memcpy(reqs.m_hierarchy, first_array[0], num_rows*MAX_COLS*sizeof(int));```
Also, for memcmp and memcpy functions how to correctly pass an array with each representation.

I am bit confused, for example, why not use
Code:
`memcpy(reqs.m_hierarchy, first_array, num_rows*MAX_COLS*sizeof(int));`
thanks,

zahid

2. Above, I have declared (defined) two 2D arrays namely first_array, and second_array.
Code:
```#define MAX_COLS 4

int **first_array;
int second_array[][MAX_COLS];```
Actually, you have not created two arrays.

The first is only a pointer to a pointer to an int, but not initialized.

The second cannot compile as you have not provided the first dimension!

You need to create a working program that demonstrates what you are asking about. Turn on and turn up the warning level on your compiler.

3. int **first_array implies that it has a dynamic number of columns (not necessaily a "ragged" array, but a fixed number of columns that is only able to be determined at runtime) as well as a dynamic number of rows. If it has a fixed number of columns determinable at compile time, then it should be:
Code:
`int (*first_array)[NUM_COLS];`
Note that NUM_COLS is a better name for a fixed number of columns. MAX_COLS implies that it could be less. Your print routine assumes that it always uses "MAX_COLS" columns.

If the number of columns is dynamic then your print function will not work properly in general.

4. Originally Posted by algorism
int **first_array implies that it has a dynamic number of columns (not necessaily a "ragged" array, but a fixed number of columns that is only able to be determined at runtime) as well as a dynamic number of rows. If it has a fixed number of columns determinable at compile time, then it should be:
Code:
`int (*first_array)[NUM_COLS];`
Note that NUM_COLS is a better name for a fixed number of columns. MAX_COLS implies that it could be less. Your print routine assumes that it always uses "MAX_COLS" columns.

If the number of columns is dynamic then your print function will not work properly in general.

I figured out, that normally, my second dimension was always fixed and I could always workout the size of first dimension. Therefore, I started to drop the pointer notation, and instead defining arrays as:
Code:
```#define NUM_COLS 4
#define MAX_ROWS 13
int first_array[MAX_ROWS][NUM_COLS]```
As noted, the first dimension can go to the maximum of 13, but it can be smaller.

I have a follow up question, with such notation, if I want to copy contents between two 2d arrays, is the following way using "memcpy" correct.
Code:
```int p[MAX_ROWS][MAX_COLS];
int arr[3][4] = {
{1,2,3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
memcpy(p,arr,sizeof(int)*3*4);```
And, also to use memcmp function for comparing the contents of the two arrays.
Code:
```int array[2][3] = // some contents;
int array2[2][3]=// some contents;

memcmp(array, array2, sizeof(array));```

thanks,

5. > if I want to copy contents between two 2d arrays, is the following way using "memcpy" correct.
Yes, in the sense that it does copy all the data.
No, if you expect p[x][y] to have the same values as arr[x][y] for all the valid subscripts of arr.

The memcpy will just smear the content of the small array over the first few rows of the large array. A simple test would have revealed this to you.

If you want the small array to be just in the top-left of the large array, then you have to copy it yourself, one element at a time, using two nested loops.

Your memcmp is fine, if both arrays have identical dimensions (and composed only of integral types like int - as you have).

6. Code:
```#include <stdio.h>
#include <string.h>

#define MAX_ROWS 13  // maximum number of rows
#define NUM_COLS  4  // fixed number of columns

void prn(int a[][NUM_COLS]) {
for (int row = 0; row < MAX_ROWS; row++) {
for (int col = 0; col < NUM_COLS; col++)
printf("%2d ", a[row][col]);
putchar('\n');
}
putchar('\n');
}

int main() {
int p[MAX_ROWS][NUM_COLS] = {{ 0 }};
int arr[][NUM_COLS] = {
{ 1,  2,  3,  4},
{ 5,  6,  7,  8},
{ 9, 10, 11, 12}
};

// This works, but only because both arrays have
// the same number of columns.
memcpy(p, arr, sizeof arr);
prn(p);

memset(p, 0, sizeof p); // zero out p again

// This would work even if they had different column sizes.
for (size_t row = 0; row < sizeof arr / sizeof *arr; row++)
memcpy(p[row], arr[row], sizeof *arr);
prn(p);

return 0;
}```