2017-06-19 5 views
9

Ein klassisches Makro die Anzahl der Elemente in einem Array zu berechnen, ist dies:Gibt es eine Möglichkeit für CountOf() zu testen, ob sein Argument ein Array ist?

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

Das Problem dabei ist es nicht still, wenn das Argument einen Zeiger anstelle eines Arrays ist. Gibt es einen portablen Weg, um sicherzustellen, dass dieses Makro nur mit einem tatsächlichen Array verwendet wird?

+1

Kompilierzeit bestätigen, dass sizeof (& table [0])! = Sizeof (Tabelle [0]) und Sie werden in den meisten Fällen da sein, definitiv wenn Multi-Member-Strukturen beteiligt sind. Die Größe eines Zeigers ist auch die Größe eines Zeigers für einen Zeiger. Für Strukturen kann dies nur für eine sehr einfache Struktur gelten. Nicht perfekt, aber in den meisten Fällen eher nah am Ziel. Und tragbar. –

+0

@ B.Nadolson Während es für einige spezifische Fälle funktionieren könnte, würde ich wahrscheinlich eine Menge Kommentare geben, wo Sie es verwenden (nach dem Prinzip der geringsten Überraschung). Es gibt viele Fälle, in denen diese Überprüfung nicht korrekt funktioniert, aber ein Programmierer könnte davon ausgehen, dass dies der Fall ist. – tangrs

+1

Die Eigenschaft '(intptr_t) & table == (intptr_t) table' gilt für ein Array, im Falle eines pointer nur, wenn sie auf sich selbst zeigt, was selten ist. – Marian

Antwort

4

eine nicht tragbare integrierte Funktion verwenden, hier ist ein Makro eine statische Behauptung zu führen, dass a ein Array ist:

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

Es beide Werke mit gcc und clang. Ich benutze es, um die countof() Makro sicherer zu machen:

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

Aber ich habe keine tragbare Lösung für dieses Problem.

Verwandte Themen