Как объяснено, это слабая (*) попытка обезопасить макрос от использования с указателями (а не с истинными массивами), где он не сможет правильно оценить размер массива. Это, конечно, связано с тем, что макросы являются чисто текстовыми манипуляциями и не имеют понятия AST .
Поскольку вопрос также помечен C ++, я хотел бы отметить, что C ++ предлагает безопасную альтернативу типа: шаблоны.
#ifdef __cplusplus
template <size_t N> struct ArraySizeHelper { char _[N]; };
template <typename T, size_t N>
ArraySizeHelper<N> makeArraySizeHelper(T(&)[N]);
# define ARRAY_SIZE(a) sizeof(makeArraySizeHelper(a))
#else
# // C definition as shown in Google's code
#endif
В качестве альтернативы, скоро можно будет использовать constexpr
:
template <typename T, size_t N>
constexpr size_t size(T (&)[N]) { return N; }
Однако мой любимый компилятор (Clang) все еще не реализует их: x
В обоих случаях, поскольку функция не принимает параметры указателя, вы получите ошибку во время компиляции, если тип неправильный.
(*) слабый в том смысле, что он не работает для небольших объектов, где размер объектов является делителем размера указателя.
Просто демонстрация того, что это значение времени компиляции:
template <size_t N> void print() { std::cout << N << "\n"; }
int main() {
int a[5];
print<ARRAY_SIZE(a)>();
}
Посмотрите в действии на IDEONE .