Synlar
Synlar

Reputation: 101

How do I pass a pointer to a multidimensional array in C?

I have a two dimensional array that works with a function:

bool matrix[rows][cols];
func(rows, cols, matrix);

void func(int rows, int cols, bool matrix[rows][cols]) {
    //...
}

However, as soon as I try to have matrix in the original function modified by:

bool matrix[rows][cols];
func(rows, cols, &matrix);

void func(int rows, int cols, bool *matrix[rows][cols]) {
    //...
}

I receive an incompatible pointer type error. I am clueless as to why.

Upvotes: 7

Views: 803

Answers (4)

Spikatrix
Spikatrix

Reputation: 20244

@2501 has already answered your question, but, since you want the modified array to be reflected to the main function, you don't actually need a pointer to the array (which will complicate things more)! Just pass the array directly as you'll get the expected results!

Why, you ask?

Short answer: In C, arrays are passed by reference.

Long answer:

Always keep in mind that when you use the name of an array, it gets converted to a pointer to its first element. This is commonly referred to as "array decay".

Coming back to your code, The diagram of bool matrix[rows][cols]; would be:

+---------------------+---------------------+---------------------+---------------------+---------------------+
|                     |                     |                     |                     |                     |
|     matrix[0][0]    |     matrix[0][1]    |     matrix[0][2]    |         ...         | matrix[0][cols - 1] |
|                     |                     |                     |                     |                     |
+---------------------+---------------------+---------------------+---------------------+---------------------+
|                     |                     |                     |                     |                     |
|     matrix[1][0]    |     matrix[1][1]    |     matrix[1][2]    |         ...         | matrix[1][cols - 1] |
|                     |                     |                     |                     |                     |
+---------------------+---------------------+---------------------+---------------------+---------------------+
|                     |                     |                     |                     |                     |
|         ...         |         ...         |         ...         |         ...         |         ...         |
|                     |                     |                     |                     |                     |
+---------------------+---------------------+---------------------+---------------------+---------------------+
|                     |                     |                     |                     |                     |
| matrix[rows - 1][0] | matrix[rows - 1][1] | matrix[rows - 1][2] |         ...         | matrix[rows - 1][cols - 1] |
|                     |                     |                     |                     |                     |
+---------------------+---------------------+---------------------+---------------------+---------------------+

From the above diagram, it is clear that the first element of

bool matrix[rows][cols];

is the first subarray matrix[0][0] to matrix[0][cols - 1]. So what happens here is that the address of this subarray is being passed to the function. This is of type bool (*)[cols]. This would mean that

void func(int rows, int cols, bool matrix[rows][cols])

would work the same way as

void func(int rows, int cols, bool (*matrix)[cols])

So, for example, if you wanted to write to the third slot of the second subarray of matrix, you can use matrix[1][2] = WHATEVER; and the changes made from the function would also affect to the caller since the address was passed.


: There are a few exceptions where array "decay" doesn't occur. See Exception to array not decaying into a pointer?

Upvotes: 3

sjsam
sjsam

Reputation: 21955

A pointer to a single dimensional array, say int a[10] may look like below:

int (*ptr)[10]
       |    |______________array of 10 integers(read type and number together)
       |______a pointer to ^

A pointer to a multi dimensional array, say int a[10][10] may look like below:

int (*ptr)[10][10]
      |    |     |_________________array of 10 integers(read type and number together)
      |    |______________array of ^ 
      |______a pointer to ^

Warning: Mind the parenthesis.

*matrix[rows][cols]) is different from (*matrix)[rows][cols]). The difference is pointed out in the answer by @2501.

Upvotes: 0

Niklas Rosencrantz
Niklas Rosencrantz

Reputation: 26647

You can use a *** for a matrix.

char ***matrix = alloc_matrix(BUFFER_SIZE, BUFFER_SIZE);

char ***alloc_matrix(unsigned rows, unsigned columns) {
    char ***matrix = malloc(rows * sizeof(char **));
    if (!matrix) abort();

    for (unsigned row = 0; row < rows; row++) {
        matrix[row] = calloc(columns, sizeof(char *));
        if (!matrix[row]) abort();
        for (unsigned column = 0; column < columns; column++) {
            matrix[row][column] = NULL;
        }
    }
    return matrix;
}

Here is an example where we use malloc and pointers to create a matrix.

Upvotes: -3

2501
2501

Reputation: 25752

bool matrix[rows][cols] is an array of arrays of a type bool

bool* matrix[rows][cols] is an array of arrays of a type pointer to bool or simply bool*.

Thus if you defined your function to take an array of arrays of type bool*, you need to pass that type:

bool* m[row][col];
func( row , col , m );

If you want to have a pointer to bool matrix[rows][cols], then your approach is not correct.
A pointer to matrix has the type: bool (*pmatrix)[rows][cols]. So define your function with that type and pass the address of the matrix array:

func( rows , cols , &matrix );

Upvotes: 7

Related Questions