Простой ответ на ваш вопрос: нет способа написать функцию array_length
. Вы могли бы быть в состоянии обойтись без определения макроса, но это зависит от контекста, в котором вы будете использовать макрос.
Вы сделали общую ошибку, путая массивы и указатели в C. В C имя массива, в большинстве случаев , эквивалентно указателю на его первый элемент. Ваша функция array_length
получает массив a
в таком контексте. Другими словами, невозможно передать массив как массив в C. Вы функционируете так, как если бы он был определен так:
int array_length(int *a){
return sizeof(a)/sizeof (int);
}
, который, в основном, делит размер int *
на размер int
. Кроме того, согласно приведенному выше описанию, невозможно узнать размер массива в C в функции.
Теперь, как вы можете правильно определить его размер вне функции? Ответ заключается в том, что оператор sizeof
является одним из случаев, когда имя массива не сводится к указателю на его первый элемент. Я объяснил различия более подробно в этом ответе . Также обратите внимание, что, несмотря на внешний вид, sizeof
является оператором, а не функцией (как мы только что узнали, он не может быть функцией, потому что тогда он не сможет рассчитать размер массив).
Наконец, чтобы определить размер массива a
любого типа T
, я предпочитаю:
size_t sz = sizeof a / sizeof a[0];
Выше не зависит от типа: a
может быть любого типа выше. В самом деле, вы могли бы даже изменить тип a
, и вам не нужно менять вышеуказанное.