2010-01-25 6 views
17

Ich weiß, dass sizeof eine Kompilierzeit Berechnung ist, aber das scheint mir seltsam: Der Compiler kann entweder einen Typnamen oder einen Ausdruck (von dem er den Typ ableitet). Aber wie identifizieren Sie einen Typ innerhalb einer Klasse? Es scheint die einzige Möglichkeit zu sein, einen Ausdruck zu übergeben, der ziemlich klobig erscheint.Warum analysiert sizeof Strukturelemente nicht?

struct X { int x; }; 
int main() { 
    // return sizeof(X::x); // doesn't work 
    return sizeof(X()::x); // works, and requires X to be default-constructible 
} 
+11

Unterstützung für 'sizeof (X :: x)' in C++ 0x enthalten ist (vgl http://www.open -std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html). –

+0

@James +1 bei Ihrem Kommentar. Meine Antwort (gelöscht) hätte eigentlich ein Kommentar sein sollen, denn Tom hat C++ 0x nicht erwähnt. Vielleicht will er es in C++ 98 :) – AraK

+0

Ja, meine Frage ist über C++ 98. Aber selbst wenn ich mit "-std = C++ 0x" baue, funktioniert es nicht (GCC 4.3.2). Gibt es Compiler-Implementierungen, die es noch unterstützen? – Tom

Antwort

27

Eine alternative Methode funktioniert ohne einen Standardkonstruktor zu benötigen:

return sizeof(((X *)0)->x); 

Sie diese in einem Makro wickeln kann, so ist es besser liest:

#define member_sizeof(T,F) sizeof(((T *)0)->F) 
+0

AFAIK, Dereferenzierung eines Null-Zeigers ist undefiniertes Verhalten. Gilt diese Regel auch in diesem Fall? – AraK

+5

@AraK: Ich denke nicht: "Der Operand [von sizeof] ist entweder ein Ausdruck, * der nicht ausgewertet wird *, oder eine eingeklammerte Typ-ID" (5.3.3/1; Hervorhebung meins). –

+2

Der NULL-Zeiger wird nie dereferenziert. Dies ist eine Kompilierungszeitoperation. Es geht nur darum, den Compiler dazu zu bringen, The Right Thing (tm) zu machen. –

0

Was offsetof? Schau mal here. Schauen Sie auch here, die beide sizeof und offsetof in einem Makro kombiniert.

Hoffe, das hilft.

+0

Das hilft nicht, weil der Compiler (während er benötigt wird, um die Elemente der Struktur in der deklarierten Reihenfolge anzuordnen) frei ist, sie zu puffern, wie es für notwendig erachtet. – dmckee

+0

dmckee: Oh, Ok..danke für deine Eingabe! Prost :) – t0mm13b

10

Hier ist eine Lösung ohne den bösen Null-Zeiger dereferenzieren;)

struct X { int x; }; 

template<class T> T make(); // note it's only a declaration 

int main() 
{ 
    std::cout << sizeof(make<X>().x) << std::endl; 
} 
+0

oh, das ist trixy! – Tom

+1

Könntest du nicht einfach 'extern T fakeT sagen; sizeof (fakeT.x); '? – MSalters