Waseem Francis
Waseem Francis

Reputation: 211

Can someone explain this behavior?

I write a simple code that get's a matrix of maximum M lines and I can't understand why it is giving me a strange output :

for M=50 :

"the cell [1][0] is : 17273520" (I get random outputs every time)

for M=4 :

"the cell [1][0] is : 0" (always)

#define M 50
void printImage(int a[][M]){
printf("the cell [1][0] is : %d",a[1][0]);
}

int main(){
int a[3][4] = {0};
printImage(a);
}

Can anybody explain what exactly is for M ? how it works ? and how can I make the function work for matrices that has less than M lines ?

Upvotes: 1

Views: 81

Answers (3)

Eugene
Eugene

Reputation: 2918

You've defined a matrix with dimensions 3x4, altogether 12 ints. But in the function, you've defined the second dimension to be 50, which exceeds the real dimension. When you try to read a value from [1][0] it goes to position 50 which is very far from the last initialized value in position 11. That is why you get some random value.

Upvotes: 0

A two dimensional array a in C is an array of arrays. Each member of a therefore has to be of the same size. The second size parameter in the definition is that size.

What you pass to printImage is a two dimensional array that decays to a pointer. It points to the first array element of a.

Now, since multidimensional pointer arithmetic a[i][j] for a true two dimensional array is *(a + i * M + j) we see that M is part of the type definition.

If you specify that you will pass a[][50] but in fact pass a[][4], the indexing for a[1][0] will be way outside the array bounds.

Since accessing outside of an array boundary is undefined behavior, anything can happen, you get some random value. But the program can just the same crash or format you hard-drive.

This is also why you should always build your programs with as high a warning level as possible (even turn most into hard errors). For instance, GCC can protect you with the following helpful diagnostic:

error: passing argument 1 of 'printImage' from incompatible pointer type [-Wincompatible-pointer-types]


If you need for the array elements of the two dimensional array to be of different sizes. You can specify that the function accepts a variable length array. Pass the size of the array dimensions first, and then the array with these dimensions:

void printImage(size_t n, size_t m, int a[n][m])
{
  // a is a VLA with dimensions specified by n and m
  // pointer arithmetic will be *(a + i * m + j) 
}

The above is valid C99.

Upvotes: 4

Gerhardh
Gerhardh

Reputation: 12404

You define a as array a[3][4] but in printImage you tell your compiler that the last dimension is 50 instead of 4. With that you mess up memory map of your array and the compiler reads wrong memory location which is far behind the array.

You should always use the correct size. This could be done like this:

 int a[3][M]; 

in main().

Upvotes: 3

Related Questions