Знайдена вами поведінка - це насправді велика бородавка мовою С. Кожного разу, коли ви оголошуєте функцію, яка приймає параметр масиву, компілятор ігнорує вас і змінює параметр на покажчик. Отже всі ці декларації поводяться як перші:
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)
a буде вказівником на int у всіх чотирьох випадках. Якщо ви передасте масив у функцію, він негайно розкладеться на вказівник на його перший елемент. (У 64-бітовій системі 64-розрядний вказівник вдвічі більший, ніж 32-розрядний int, тому ваше співвідношення sizeof повертається 2.)
Єдиною метою цього правила є підтримка зворотної сумісності з історичними компіляторами, які не підтримували передачу сукупних значень як аргументів функції.
Це не означає, що неможливо передати масив функції. Ви можете обійти цю бородавку, вставивши масив у структуру (це в основному мета C ++ 11's std :: масив):
struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0])); /* prints 5 */
}
або передавши вказівник на масив:
void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */
}
У випадку, якщо розмір масиву не є константа часу компіляції, ви можете використовувати техніку вказівника на масив із масивами C99 змінної довжини:
void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */
}