2017-06-19 40 views
9

Klasyczny makro obliczyć liczbę elementów w tablicy jest taka:Czy istnieje sposób dla countof() do sprawdzenia, czy jego argumentem jest tablica?

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

Problemem jest to, że nie cicho, jeśli argument jest wskaźnikiem zamiast tablicy. Czy istnieje przenośny sposób na zapewnienie, że to makro jest używane tylko z rzeczywistą tablicą?

+1

Skompiluj czas twierdząc, że sizeof (& table [0])! = Sizeof (table [0]) i będziesz tam w większości przypadków, zdecydowanie gdy zaangażowane są struktury wieloczłonowe. Rozmiar wskaźnika jest także wielkością wskaźnika do wskaźnika. W przypadku struktur może to dotyczyć tylko bardzo prostej struktury. W większości przypadków nie jest idealny, ale raczej zbliżony do celu. I przenośny. –

+0

@ B.Nadolson Chociaż może to działać w niektórych szczególnych przypadkach, prawdopodobnie umieszczę wiele komentarzy w miejscu, w którym go używasz (zgodnie z zasadą najmniejszej niespodzianki). W wielu przypadkach kontrola ta nie działa poprawnie, ale programista może założyć, że tak. – tangrs

+1

Właściwość '(intptr_t) i tabela == (intptr_t) table' jest poprawna dla tablicy, w przypadku wskaźnika posiada ona tylko wtedy, gdy wskazuje na siebie, co jest rzadkie. – Marian

Odpowiedz

4

Korzystanie z non-przenośne wbudowaną funkcję, o to makro do wykonywania statycznych twierdzenie, że a jest tablicą:

#define assert_array(a) \ 
    (sizeof(char[1 - 2 * __builtin_types_compatible_p(typeof(a), typeof(&(a)[0]))]) - 1) 

To działa zarówno gcc i clang. Używam go, aby countof() makro bezpieczniejsze:

#define countof(a) (sizeof(a)/sizeof(*(a)) + assert_array(a)) 

Ale nie mam przenośne rozwiązanie dla tego problemu.