Why does not it work to pass the matrix to work if it is statically declared without mentioning the size in the header of the function?

advertisements

I am trying to make the code below work, but as far as I have read, there are two options to pass a matrix to a function:

  1. specify the size of the matrix in header like this: void f(int v[100][100], int n)
  2. dynamically alocate it instead of int a[100][100]

Why wouldn't it work like in the code below? Isn't saying int a[100][100] the same as allocating it dynamically? Isn't a[i][j] the same as * ( *(a+i)+j)?

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

int main()
{
    int a[100][100],n=5,i,j;
    f(a,n);
    return 0;
}


Arrays decay to pointers, that's why you can write:

void foo(int *p);
void foo(int p[]); // equivalent (use the above form)

int v[100];
foo(v);

For a multidimension array, only the first order array "decays". So a matrix (think of it as an array of arrays) decays to pointer to array:

void foo(int (*p)[100]);
void foo(int p[][100]);   // equivalent (use the above form)

int m[100][100];
foo(m);


The reason has to do with memory layout:

One dimension array:

char v[3] = {'a', 'b', 'c'};

| a | b | c |

As you can see it is fairy trivial to access this via a char * pointer.

Two dimension array:

char m[2][3] = {{'a', 'b', 'c'}, {'d', 'e', 'f'}};

| a | b | c | d | e | f |
|           |           |

The above array could not decay to a char **. A char ** would have this layout:

| addr | addr | addr | ...

That is in memory there would be pointers to char stored.

So m can decay to pointer to array 3 of char char (*p)[3]. The 3 has to be known, because that gives the size of the deferenced object, which absolutely needs to be known: for the dereference and pointer arithmetics to work (e.g. p++)

char (*p)[3]:

| a | b | c | d | e | f |
|           |           |

So the first p element, p[0] is the char[3] array {a,b,c} and p[1] is the char[3] array {d,e,f}


Note I used char to better show elements as characters. But those are not C-strings as they are not NULL terminated. Substitute with int if it makes you more comfortable.