Le comportement que vous avez trouvé est en fait une grosse verrue en langage C. Chaque fois que vous déclarez une fonction qui prend un paramètre de tableau, le compilateur vous ignore et change le paramètre en pointeur. Donc, ces déclarations se comportent toutes comme la première:
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)
a sera un pointeur vers int dans les quatre cas. Si vous passez un tableau à func, il se désintégrera immédiatement en un pointeur vers son premier élément. (Sur un système 64 bits, un pointeur 64 bits est deux fois plus grand qu'un entier 32 bits, donc votre ratio sizeof renvoie 2.)
Le seul objectif de cette règle est de maintenir la compatibilité ascendante avec les compilateurs historiques qui ne prenaient pas en charge le passage de valeurs d'agrégation en tant qu'arguments de fonction.
Cela ne signifie pas qu'il est impossible de passer un tableau à une fonction. Vous pouvez contourner cette verrue en incorporant le tableau dans une structure (c'est essentiellement le but de std :: array 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 */
}
ou en passant un pointeur vers le tableau:
void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */
}
Dans le cas où la taille du tableau n'est pas une constante de compilation, vous pouvez utiliser la technique du pointeur vers un tableau avec des tableaux de longueur variable C99:
void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */
}