El comportamiento que encontró es en realidad una gran verruga en el lenguaje C. Siempre que declara una función que toma un parámetro de matriz, el compilador lo ignora y cambia el parámetro a un puntero. Entonces todas estas declaraciones se comportan como la primera:
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)
a será un puntero a int en los cuatro casos. Si pasa una matriz a func, inmediatamente se convertirá en un puntero a su primer elemento. (En un sistema de 64 bits, un puntero de 64 bits es dos veces más grande que un int de 32 bits, por lo que su tamaño de relación devuelve 2.)
El único propósito de esta regla es mantener la compatibilidad con versiones anteriores de los compiladores históricos que no admitían el paso de valores agregados como argumentos de función.
Esto no significa que sea imposible pasar una matriz a una función. Puede evitar esta verruga incrustando la matriz en una estructura (este es básicamente el propósito de std :: matriz de C ++ 11):
struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0])); /* prints 5 */
}
o pasando un puntero a la matriz:
void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */
}
En caso de que el tamaño de la matriz no sea una constante en tiempo de compilación, puede usar la técnica de puntero a matriz con matrices de longitud variable C99:
void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */
}