0

I encountered a problem in reading a piece of C code. code show as below :

#define size_of_attribute(Struct, Attribute) sizeof(((Struct*)0)->Attribute)

The function of this macro function is gets the length of the attribute in the struct. I know what this function is for, but i can't understand the meaning of "((Struct*)0)".

I will appeaciate If you can give me some explanation :).

3 Answers3

2

The constant value 0 qualifies as a null pointer constant. The expression (Struct*)0 is therefore casting that null pointer constant to a pointer of type Struct *. The expression then gets the Attribute member.

Attempting to evaluate ((Struct*)0)->Attribute would result in a null pointer defererence, however this expression is the argument to the sizeof operator. This means the expression is not actually evaluated but simply examined to determine its type.

So sizeof(((Struct*)0)->Attribute) gives you the size of the Attribute member of the struct named Struct without having to have an object of that type.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    This may still qualify as a dereference even though it's under `sizeof`; the special case for `sizeof(*p)` is not 100% unambiguously applicable to `sizeof(p->m)`. See the very similar discussion about defining your own `offsetof`, [here](https://stackoverflow.com/a/57342272). – zwol Dec 10 '20 at 14:19
0

It's casting a null pointer to the Struct* type so it can determine the size of the attribute of that struct. Normally, reading an attribute from NULL is illegal, but for sizeof, it doesn't actually read anything, it just looks at the definition of the struct to determine the statically defined size of the attribute of any such struct.

At least for C++, this is useful because unlike a non-pointer-based:

sizeof(Struct{}.Attribute)

it doesn't require Struct to have a default constructor. A pointer can be made with no knowledge of how to construct the object, while an actual object (even if none is actually constructed) must still be constructed in a valid way, and you can't say with any reliability how an arbitrary struct can be legally constructed.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • To be more precise: `sizeof` does not _evaluate_ its argument, hence no null-pointer dereference: https://en.cppreference.com/w/cpp/language/sizeof – Benjamin Maurer Dec 10 '20 at 14:07
  • @EricPostpischil: I was using it loosely, but sure. – ShadowRanger Dec 10 '20 at 14:16
  • can anyone clarify a bit where it is indispensable to use this way to get the sizeof internal members of `struct` ? – IrAM Dec 10 '20 at 14:30
  • @IrAM: Gave an example. – ShadowRanger Dec 10 '20 at 14:38
  • @ShadowRanger so basically to recreate any member of `struct` with correct size( may be when struct is opaque or not known in the context of program) – IrAM Dec 10 '20 at 14:52
  • @IrAM: It won't work for *opaque* structs even using pointers; if all you have a forward declaration, not the definition of the struct, the compiler won't know the size (or even the name) of its members. But non-opaque structs still come with all sorts of rules for constructing them that, even if it might theoretically be possible to determine them programmatically with recursive template metamagic (I don't know if that's possible in the general case), it's just not worth doing when you can just fake a pointer. – ShadowRanger Dec 10 '20 at 15:01
0

This is basically accessing a member variable type without actually mentioning / creating any variable of that structure type.

Here,

  • the 0 is casted to the structure type pointer, and
  • then that pointer is used to access the member variable
  • which is used as the operand of sizeof operator.

Since sizeof is a compile time operation, the NULL dereference never actually executes at runtime.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261