1

As per this https://stackoverflow.com/a/3912959/1814023 We can declare a function which accepts 2D array as

void func(int array[ROWS][COLS]).

And as per this, http://c-faq.com/aryptr/pass2dary.html they say "Since the called function does not allocate space for the array, it does not need to know the overall size, so the number of rows, NROWS, can be omitted. The width of the array is still important, so the column dimension NCOLUMNS (and, for three- or more dimensional arrays, the intervening ones) must be retained."

I tried this and it works... Note that I have changed the size of column.

#include <stdio.h>
#define ROWS 4
#define COLS 5

void func1(int myArray[][25])
{
    int i, j;

    for (i=0; i<ROWS; i++)
    {
        for (j=0; j<COLS; j++)
        {
            myArray[i][j] = i*j;
            printf("%d\t",myArray[i][j]);
        }
        printf("\n");
    }
}

int main(void)
{
    int x[ROWS][COLS] = {0};
    func1(x);
    getch();
    return 0;
}

My question is, why in the CFAQ link(http://c-faq.com/aryptr/pass2dary.html) they say "The width of the array is still important"? even though I have provided wrong column size. Can someone please explain?

9
  • That shouldn't compile, really. You're trying to pass a int(*)[5] (after decay, of course) as a int(*)[25]. Commented Oct 25, 2013 at 11:58
  • 3
    Simple enough, actually. To index an element in the first row (row 0) you just need to know the column number. index = col. When row is 0, the width is unimportant. However to access an element on any other row, you must also know the number of columns wide it is, since the equation then becomes index = row*numCols + col - So, what you've done should crash. If it doesn't, it's just luck each time you execute it. The idea of setting COLS to 25 means that when i=ROWS-1 and j=COLS-1, means that for the last element, index is calculated as index = (4-1)*25 + (5-1)!! Baaaad! Commented Oct 25, 2013 at 12:07
  • @chris: it 'compiles' because the code is calling func() but defines func1(). So the called function isn't the defined function (aka 'there is a typo in the question'). You should still get warnings (at least) for calling an undeclared function, if you use a C99 or later compiler. Since the code uses getch(), it is probably running on Windows and therefore is using an antique C89 compiler (aka MSVC). Commented Oct 25, 2013 at 13:40
  • @JonathanLeffler, Oh, good catch, although I can say I use a modern C compiler on Windows when I have to use C :p Commented Oct 25, 2013 at 13:43
  • @JonathanLeffler: Sorry for the mistake in function mismatch. I did modified the code and executed on (gcc)Mingw. and on Visual studio 2010. Both compilers are giving warning. But what I didn't understand is, why we need to pass the column size. Even I did pass 1 as the column size and it worked. I know when the compile does myArray[1][2], internally it will treat it as *(*(myArray+1)+2). I did not understand the concept of passing column size to function. Commented Oct 28, 2013 at 4:16

2 Answers 2

1

This is what you get for using array notations to represent pointers. Contrived example:

#include <stdio.h>

void size(int myArray[][25], int rows, int cols)
{
    printf("sizeof(int [%d][%d]) = %d\n", rows, cols, sizeof(myArray));
}

int main(void)
{
    int arr1[4][4];
    int arr2[4][5];
    int arr3[5][5];

    size(arr1, 4, 4);
    size(arr2, 4, 5);
    size(arr3, 5, 5);

    printf("sizeof(int *) = %d\n", sizeof(int *));

    return 0;
}

If you try to run this, all 4 sizes will be the same, even though the arrays passed are of different sizes.
Array types in C is just syntactic sugar - multidimensional arrays make no sense in a linear memory model. With linear memory model to access an element of a simple array you must know 2 things: base address and index offset, so you can write *(base+indexOffset). To index an element in a two dimensional array you must know two additional things: size of your first dimension and its offset, so you can write *(base+dimensionSize*dimensionOffset+indexOffset). Array notation just does all this complicated math for you, but you must still provide the required data to the compiler. Its up to you to ensure data integrity :)

Sign up to request clarification or add additional context in comments.

Comments

0

When I compile and run your program (after fixing the func/func1 confusion and altering the getch, on Ubuntu 12.04) this is what happens

$ gcc crashme.c -o crashme
crashme.c: In function ‘main’:
crashme.c:23:13: warning: passing argument 1 of ‘func1’ from incompatible pointer type [enabled by default]
crashme.c:4:6: note: expected ‘int (*)[25]’ but argument is of type ‘int (*)[5]’
jamie@jamie-Ideapad-Z570:~/temp$ ./crashme 
0   0   0   0   0   
0   1   2   3   4   
0   2   4   6   8   
0   3   6   9   12  
Segmentation fault (core dumped)

If you add a line

printf("%ld", sizeof(x));

Immediately after the int x[ declaration you will see that the size is that of a 4 x 5 x sizeof int ( 80 on my system ) so the declaration size is available to sizeof and so useful for malloc calls etc.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.