tags:

views:

238

answers:

3

I know that sizeof is a compile-time calculation, but this seems odd to me: The compiler can take either a type name, or an expression (from which it deduces the type). But how do you identify a type within a class? It seems the only way is to pass an expression, which seems pretty clunky.

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
}
+16  A: 

An alternate method works without needing a default constructor:

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

You can wrap this in a macro so it reads better:

#define member_sizeof(T,F) sizeof(((T *)0)->F)
Greg Hewgill
AFAIK, dereferencing a NULL pointer is undefined behavior. Does that rule apply in this case also?
AraK
@AraK: I don't think so: "The operand [of sizeof] is either an expression, *which is not evaluated*, or a parenthesized type-id" (5.3.3/1; emphasis mine).
James McNellis
The NULL pointer is never dereferenced. This is a compile-time operation. It's just merely to get the compiler to do The Right Thing(tm).
Jim Buck
+1 Thanks guys, it seems a nice trick actually.
AraK
Isn't that 'return sizeof...' the same as the offsetof?
tommieb75
@tommieb75: The *sizeof* `x` is the number of bytes occupied by the `x` member. The *offsetof* `x` is the number of bytes `x` is offset from the start of its enclosing structure `X`.
Greg Hewgill
A: 

What about offsetof? Have a look here. Also have a look here, which combines both sizeof and offsetof into a macro.

Hope this helps, Best regards, Tom.

tommieb75
Doesn't help, because the compiler (while required to order the elements of the structure in the declared order) is free to pad them as it deems necessary.
dmckee
dmckee: Oh, Ok..thanks for your input! Cheers :)
tommieb75
+9  A: 

Here is a solution without the nasty null pointer dereferencing ;)

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;
}
FredOverflow
oh, that's trixy!
Tom
Couldn't you just say `extern T fakeT; sizeof(fakeT.x);` ?
MSalters