This question already has an answer here:
-
Is there a standard function in C that would return the length of an array?
6 answers
-
Array-size macro that rejects pointers
9 answers
I've seen several macros for array length floating around:
From this question:
#define length(array) (sizeof(array)/sizeof(*(array)))
#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
#define SIZE(array, type) (sizeof(array) / (sizeof(type))
And Visual Studio's _countof
:
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
What I'd like to know is:
- What's the difference between those using
array[0]
and *array
?
- Why should either be preferred?
- Do they differ in C++?
Here's a better C version (from Google's Chromium project):
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
It improves on the array[0]
or *array
version by using 0[array]
, which is equivalent to array[0]
on plain arrays, but will fail to compile if array
happens to be a C++ type that overloads operator[]()
.
The division causes a divide-by-zero operation (that should be caught at compile time since it's a compile-time constant expression) for many (but not all) situations where a pointer is passed as the array
parameter.
See Is there a standard function in C that would return the length of an array? for more details.
There's a better option for C++ code. See Compile time sizeof_array without using a macro for details.
- What's the difference between those using array[0] and *array?
- Why should either be preferred?
- Do they differ in C++?
(1) No difference in C. No difference for an actual raw array in C++.
(2) No technical grounds to prefer one or the other, but newbies might be confused by the pointer dereference.
(3) In C++ you would normally not use the macro, because it's very unsafe. If you pass in a pointer instead of an actual raw array, code will compile but yield incorrect result. So in C++ you would/should instead use a function template, like …
#include <stddef.h>
typedef ptrdiff_t Size;
template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }
This only accepts actual raw array as argument.
It's part of a triad of functions startOf
, endOf
and countOf
that it's very convenient to define so that they can be applied to both raw arrays and standard library containers. As far as I know this triad was first identified by Dietmar Kuehl. In C++0x startOf
and endOf
will most probably be available as std::begin
and std::end
.
Cheers & hth.,
1) Nothing, the value of an array is a pointer to it's first element. So *array == array[0]
2) Personal Preference
3) No
Note that this macro wont work if called inside a function where the array is passed as a parameter into the function. This is because the array object passed "decays" into a pointer rather than a deep copy.