2010-01-25 20 views
17

Sé que sizeof es un cálculo en tiempo de compilación, pero me parece extraño: el compilador puede tomar un nombre de tipo o una expresión (de la cual deduce el tipo). ¿Pero cómo identificas un tipo dentro de una clase? Parece que la única forma es pasar una expresión, que parece bastante torpe.¿Por qué sizeof parse struct members?

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

Soporte para 'sizeof (X :: x)' se incluye en C++ 0x (cf. http://www.open -std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html). –

+0

@James +1 en tu comentario. Mi respuesta (eliminada) debería haber sido un comentario en realidad, porque Tom no mencionó C++ 0x. Tal vez lo quiere en C++ 98 :) – AraK

+0

Sí, mi pregunta es sobre C++ 98. Sin embargo, incluso si construyo con '-std = C++ 0x', no funciona (GCC 4.3.2). ¿Hay alguna implementación de compilador que lo soporte todavía? – Tom

Respuesta

27

Un método alternativo funciona sin necesidad de un constructor por defecto:

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

Puede terminar con esto en una macro para que se lea mejor:

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

AFAIK, desreferenciar un puntero NULL es un comportamiento indefinido. ¿Esa regla también se aplica en este caso? – AraK

+5

@AraK: No lo creo: "El operando [de sizeof] es una expresión, * que no se evalúa *, o un ID de tipo entre paréntesis" (5.3.3/1; énfasis mío). –

+2

El puntero NULL nunca se desreferencia. Esta es una operación en tiempo de compilación. Simplemente es para que el compilador haga Lo correcto (tm). –

0

¿Qué hay de offsetof? Eche un vistazo here. También tenga un aspecto here, que combina sizeof y offsetof en una macro.

Espero que esto ayude.

+0

No ayuda, porque el compilador (aunque es necesario ordenar los elementos de la estructura en el orden declarado) puede rellenarlos como lo considere necesario. – dmckee

+0

dmckee: Oh, Ok ... gracias por tu aporte! Saludos :) – t0mm13b

10

Aquí es una solución sin el puntero nulo desagradable eliminación de referencias;)

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, eso es trixy! – Tom

+1

¿No podría simplemente decir 'extern T fakeT; sizeof (fakeT.x); '? – MSalters