1

Possible Duplicate:
How do I use arrays in C++?

One dimensional array as a function parameter:

#include <stdio.h>
#include <string.h>

int func(int a[], int n)
{
    int i;
    for(i = 0; i < n; i++)
        printf("%d ", a[i][j]);
}

int main(void)
{   
    int a[2] = {1,2};
    func(a, 2);
}

it compiles and runs correctly.

But when a two-dimensional array as a function parameter:

#include <stdio.h>
#include <string.h>

int func(int a[][], int n)
{
    int i, j;
    for(i = 0; i < n; i++)
        for(j = 0 ; j < n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
}

int main(void)
{   
    int a[2][2] = {{1,2}, {3,4}};
    func(a, 2);
}

it can not compile correctly. I must modify the code like this:

#include <stdio.h>
#include <string.h>

int func(int a[][2], int n)
{
    int i, j;
    for(i = 0; i < n; i++)
        for(j = 0 ; j < n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
}

int main(void)
{   
    int a[2][2] = {{1,2}, {3,4}};
    func(a, 2);
}

I do not know why? Anybody can explain how it works? Many thanks.

Community
  • 1
  • 1
imsrch
  • 1,152
  • 2
  • 11
  • 24
  • `int a[]` then `a[i][j]` - How on Earth does this compile correctly? –  Jan 01 '13 at 17:02
  • This question is not a duplicate of "How do I use arrays in C++". That question is so broad anyway (so poorly phrased). This question is more specific (although in need of some editing for English-correctness). Also, even though some of what is addressed in that question relate to here, they are often specific to C++ whereas this question should be limited to C and be oriented toward C idioms. If this is a duplicate of another question on SO, let's get the correct one listed here. – labyrinth Feb 04 '15 at 16:17

5 Answers5

7

Arrays (both one and multidimensional) in c reside in continuous memory blocks. This means that when you define char a[3], the array is laid out in memory like this (forgive my terrible ascii art skills):

| a[0] | a[1] | a[2] |

For a two-dimensional array char a[2][3], the layout is like this:

| a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] |  
                              ^
                              +--- first row ends here

Therefore, when you index into a two-dimensional array a[i][j], the compiler generates code equivalent to this:

*(a + i*3 + j)

Which can be read as "skip i rows and take cell j in that row". To accomplish this, the compiler must know the length of the row (which is the second dimension). This means that the second dimension is a part of the type definition!

As such when you want pass a 2d array into a function, you must specify the needed dimension for the type definition.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
3

Recent (e.g. C2011, and perhaps C99) C standards enable variable length array so the following function does work

int
sum (int n, int t[n][n])
{
  int s = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      s += t[i][j];
  return s;
}   

this is compiled without warnings with gcc-4.7 -std=gnu99 -Wall -O -c ex.c and the generated assembler is what you expect

As to why int t[][] cannot work, it is because each element of the entire t would be of type int [] which has indeterminate size.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

Here is a quite good explaintation: http://www.eskimo.com/~scs/cclass/int/sx9a.html

Adam Sznajder
  • 9,108
  • 4
  • 39
  • 60
0

Without the second dimension to the array the compiler doesn't know how to index into it. This is because the compiler does some arithmetic with a pointer to work out where to find the value in memory.

Will
  • 4,585
  • 1
  • 26
  • 48
0

Arrays in C are quite "weak", and typically represented at run-time by just a pointer to the first element. When you declare something like int a[][], it's not possible to know how to compute the address of each element, since the type declaration doesn't say. This is why it won't compile, since the type is invalid.

If you could have int a[][], and then called it passing either int big[8][8] or int small[2][2], there's no way for the code inside the function to magically "adapt" for the proper address computation for these different arrays. This is why it won't work.

You can write a general function like int *matrix, size_t width and do the address computation manually, i.e. element "matrix[i][j]" is at matrix[i * width + j] for a row-major ordering.

unwind
  • 391,730
  • 64
  • 469
  • 606