Reputation: 35
I apologize in advance if this has been asked before –– I couldn't find it.
This is merely a weird bug that I do not understand which has little (if any) practicality. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void print_matrix(int a[4][3], int i, int j)
{
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
return;
}
int main(void)
{
int i, j;
int array[3][5];
for (i = 0; i < 3; i++)
{
for(j = 0; j < 5; j++)
{
scanf("%d",&(array[i][j]));
}
}
printf("array[2][1] = %d\n", array[2][1]);
print_matrix(array, 2, 1);
printf("array[0][4] = %d\n", array[0][4]);
print_matrix(array, 0, 4);
return 0;
}
I declared a matrix of size [3][5], but when I use this matrix in another function and call it with size [4][3], it returns weird results. Can someone explain the way memory is accessed in this scenario?
Upvotes: 2
Views: 60
Reputation: 170055
Your code has undefined behavior, so anything can happen. The function's first argument is expected to be a int (*a)[3]
, a pointer to an array of 3 integers. Arrays as function parameters always decay to pointers, and in this case a pointer to an array. However when you pass array
, it decays to a int(*)[5]
, a pointer to an array of 5 integers.
According to the C11 standard's following sub-sections:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.
Since the pointer types are incompatible, the compiler is allowed to emit any code it wants, without limitations. The code doesn't even have to make sense, that is the meaning of undefined behavior.
But GCC (and other compilers for sure) can emit the following warning for the code:
warning: passing argument 1 of 'print_matrix' from incompatible pointer type [-Wincompatible-pointer-types]
So always compile with warnings enabled, and heed them!
As for what is most probably happening, you need to consider how array access happens for multidimensional arrays. The size 3 is part of the array definition so that when you write a[i][j]
it would be interpreted as:
*(a + i * 3 + j)
But this is not the correct arithmetic for array
, there the correct access is equivalent to
*(array + i * 5 + j)
So in essence, by reading array
through a
, you access the wrong cells.
Upvotes: 2