2010-12-11 10 views

Odpowiedz

4

To?

#define _countof(a) (sizeof(a)/sizeof(*(a)))

+3

która byłaby niebezpieczna, kiedy to wskaźnik (w porównaniu z tablicy). makro _countof jest bezpieczne. – Uri

5

nie jestem świadomy jednej dla GCC, ale Linux używa GCC's __builtin_types_compatible_p builtin aby ich ARRAY_SIZE() makro bezpieczniejsze (będzie to powodować przerwy gromadzeniu jeśli zastosowane do wskaźnika):

/* &a[0] degrades to a pointer: a different type from an array */ 
#define __must_be_array(a) \ 
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0]))) 

#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]) + __must_be_array(arr)) 

Uwaga: Myślę, że BUILD_BUG_ON_ZERO() makro ma mylące nazwy (powoduje awarię gromadzeniu jeśli wyrażenie jest nie zero i zwraca 0 inaczej):

/* Force a compilation error if condition is true, but also produce a 
    result (of value 0 and type size_t), so the expression can be used 
    e.g. in a structure initializer (or where-ever else comma expressions 
    aren't permitted). */ 
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 

Myślę, że nazewnictwo tego makra pochodzi od obejrzenia go w dwóch częściach: BUILD_BUG_ON to, co robi makro, gdy wyrażenie jest prawdziwe, a ZERO to wartość "zwrócona" przez makro (jeśli nie ma kompilacji przerwa).

10

Korzystanie C++ 11, nie-makro forma jest:

char arrname[5]; 
size_t count = std::extent< decltype(arrname) >::value; 

I extent można znaleźć w nagłówku type_traits.

Lub jeśli chcesz to wyglądać nieco ładniejszy, zawinąć go w ten sposób:

template < typename T, size_t N > 
size_t countof(T (& arr)[ N ]) 
{ 
    return std::extent< T[ N ] >::value; 
} 

A potem staje się:

char arrname[5]; 
size_t count = countof(arrname); 

char arrtwo[5][6]; 
size_t count_fst_dim = countof(arrtwo); // 5 
size_t count_snd_dim = countof(arrtwo[0]); // 6 

Edit: Właśnie zauważyłem "C" flagę zamiast "C++". Więc jeśli jesteś tutaj dla C, uprzejmie proszę zignoruj ​​ten post. Dzięki.

+0

Jedna różnica: przynajmniej na MSVC, std :: extent :: value zwraca 0, podczas gdy _countof zwraca odpowiednią liczbę. – Ash

+0

Testowałem również na GCC i to również zwraca 0. – Ash

+3

Musisz wykonać funkcję countex constexpr, w przeciwnym razie nie zadziała. Ponadto łatwiej jest "zwrócić N;" zamiast "std :: extent < T[ N ] > :: value;". – prgDevelop

2

Można użyć boost::size() zamiast:

#include <boost/range.hpp> 

int my_array[10]; 
boost::size(my_array); 
+1

Zwiększenie to C++, podczas gdy pytania są oznaczone jako C. – tambre

+0

Najlepsza głosowana odpowiedź to także C++, podobnie jak implementacja '_countof' w MSVC – KindDragon

+1

Nie rozważałbym uzasadnienie wysłania odpowiedzi na inny język na pytanie niezaznaczone tym językiem. – tambre