2

I saw the following weird type of macro in C (Linux) code here:

#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))

What does ((t*)0)->f) do?

How does it work?

msc
  • 33,420
  • 29
  • 119
  • 214

3 Answers3

4

The thing does exactly what the name suggests – deliver the size of a field of a struct.

what it first does is cast 0 (which is an arbitrary address) to a pointer of the type of struct.

Then it -> (access via pointer) takes the field and applies sizeof to it.

Pretty straightforward!

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • 1
    `0` is not arbitrary; it's a null pointer constant, so `(t*)0` is a null pointer. – melpomene Nov 04 '17 at 22:51
  • 1
    It is worth noting that the `sizeof` operator does not evaluate the value it is used on, or else you'd get undefined behaviour. If it is UB even so is a matter of some debate... – rodrigo Nov 04 '17 at 22:52
  • @melpomeme. Giving the pointer a name does not make it any less arbitrary in this context. Any other value would have worked as well. Also, NULL is technically an implementation dependent value that is not required to be zero. – Mad Physicist Nov 05 '17 at 04:52
  • @MadPhysicist but casting the integer 0 to a pointer type is required to give the NULL pointer. – Ajay Brahmakshatriya Nov 05 '17 at 05:06
  • @Ajay. That is just not true in general: https://stackoverflow.com/q/2597142/2988730 – Mad Physicist Nov 05 '17 at 05:19
  • @Ajay. Not to mention the fact that NULL is technically not any kind of pointer. – Mad Physicist Nov 05 '17 at 05:26
  • 1
    @MadPhysicist [C standard 6.3.2.3p3](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3) I am not saying NULL pointer should have a value 0 (a pointer is not even required to be an integer), I am just saying casting 0 to a pointer type gives a NULL pointer constant. – Ajay Brahmakshatriya Nov 05 '17 at 05:29
  • 1
    @MadPhysicist in the link you pointed, look at this [comment](https://stackoverflow.com/questions/2597142/when-was-the-null-macro-not-0#comment2606463_2597232) – Ajay Brahmakshatriya Nov 05 '17 at 05:31
3

It does what it says on the tin, like Marcus Müller explains. If you are wondering why bother with it, why can't we just do sizeof(type_of_field) instead, then consider this:

struct foo {
  struct {
    int a;
    float b;
  } bar;
};

We cannot name type_of_bar, since for the programmer it has no name. But the macro allows us to obtain the field size via a workaround, regardless.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
1

Because sizeof is computed at compile time (except in the case of variable length arrays, which is not the case here) its argument is not evaluated at runtime. It is therefore OK to cast a NULL pointer, as it's only used to indicate the field for which size is being computed.

mnistic
  • 10,866
  • 2
  • 19
  • 33