Why subtract null pointer in offsetof()?
Asked Answered
U

2

6

Linux's stddef.h defines offsetof() as:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

whereas the Wikipedia article on offsetof() (http://en.wikipedia.org/wiki/Offsetof) defines it as:

#define offsetof(st, m) \
    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))

Why subtract (char *)0 in the Wikipedia version? Is there any case where that would actually make a difference?

Uniformed answered 2/4, 2010 at 19:18 Comment(1)
You should not use/study code that may invoke undefined behavior, like the above. An implementation can use such skanky hacks because they know what kinds of undefined behavior secretly work. But what "secretly works" is totally not portable.Encyclopedic
P
8

The first version converts a pointer into an integer with a cast, which is not portable.

The second version is more portable across a wider variety of compilers, because it relies on pointer arithmetic by the compiler to get an integer result instead of a typecast.

BTW, I was the editor that added the original code to the Wiki entry, which was the Linux form. Later editors changed it to the more portable version.

Puberulent answered 2/4, 2010 at 20:16 Comment(3)
Thanks for the response. Followup question "Does (size_t)((char *)0) ever not evaluate to 0?" posted at #2582022Uniformed
Interesting - but is the second expression really any more portable, since pointer arithmetic on null pointers is undefined?Lithometeor
It's more portable in the sense that it works on more CPUs. Being undefined (by the standard) does not mean it can't work for some specific architecture(s).Puberulent
J
4

The standard does not require the NULL pointer to evaluate to the bit pattern 0 but can evaluate to a platform specific value.

Doing the subtraction guarantees that when converted to an integer value, NULL is 0.

Jezebel answered 2/4, 2010 at 19:23 Comment(1)
That's not the reason; any reasonable constant other than 0 could also be used. See my answer below.Puberulent

© 2022 - 2024 — McMap. All rights reserved.