7

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.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
Synlar
  • 101
  • 6
  • 2
    Just get rid of the `&` and the `*` and all should be well - arrays decay to pointers when passed as function parameters. – Paul R May 08 '16 at 07:22
  • 3
    What errors do you get exactly? – jboockmann May 08 '16 at 07:23
  • @pytheos it is an incompatible pointer type. My bad - looked like a lot when I did my first modification. – Synlar May 08 '16 at 07:26
  • @PaulR I wouldn't be able to modify both dimensions of the original matrix that way would I? – Synlar May 08 '16 at 07:27
  • Well this is odd. I am able to modify both dimensions from the original function with the new function despite not passing in a pointer or address. This would have to spark a new question... – Synlar May 08 '16 at 07:32
  • 1
    A couple things: (1) You really want a pointer to the first element, just as with one-dimensional arrays. (2) What you had would in fact have been a pointer to the array as a whole, except you declared the argument incorrectly. The `*` needs to be grouped with `matrix`, so parentheses are needed. But this isn't really what you want, as explained in 1. – Tom Karzes May 08 '16 at 07:33
  • 2
    `func(rows, cols, &matrix); void func(int rows, int cols, bool (*matrix)[rows][cols]) {` – BLUEPIXY May 08 '16 at 08:08
  • 1
    should be `bool (*matrix)[rows][cols]` . What you actually wrote is an array of `bool *`s – M.M May 08 '16 at 08:08
  • 2
    @Synlar trying to pass an array always passes a pointer – M.M May 08 '16 at 08:19
  • Is bool C++, or a user defined type? – granmirupa May 08 '16 at 08:40
  • 1
    @granmirupa `bool` is a macro for `_Bool` defined in stdbool.h. – 2501 May 08 '16 at 09:02
  • 1
    @Synlar When you get an error, please include the **exact** error message in your question. – Spikatrix May 08 '16 at 09:58
  • 1
    @PaulR This isn't really a dup of that. That question is about `double a[]` vs `double* a` in function arguments while this is different. This question is about passing a pointer to the array which is very different. – Spikatrix May 08 '16 at 13:21
  • 1
    @PaulR I agree with Cool Guy. The dup is far off. – 2501 May 08 '16 at 13:47
  • @CoolGuy: I disagree, but go ahead and vote to re-open - check first for other dupes though, as I suspect there are many. – Paul R May 08 '16 at 15:36

4 Answers4

7

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 );
2501
  • 25,460
  • 4
  • 47
  • 87
3

@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?

Community
  • 1
  • 1
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
0

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.

sjsam
  • 21,411
  • 5
  • 55
  • 102
-3

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.

Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424