Difficulty in understanding the offsetof MACRO
Asked Answered
C

1

5

I have been searching very long and hard (links at the very end) for an explanation of the implementation of the offsetof MACRO :

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

Particularly, the dereferencing of NULL to obtain the offset of the member in the structure. Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.

Here are some of the links I have tried understanding:

  1. http://www.viva64.com/en/b/0301/
  2. http://www.embedded.com/design/prototyping-and-development/4024941/Learn-a-new-trick-with-the-offsetof--macro
  3. http://www.geeksforgeeks.org/the-offsetof-macro/
  4. How does the C offsetof macro work?
  5. Does dereference a NULL pointer guarantee to crash a program in C/C++?

What I'm looking for and trying to understand is a step by step , broken down understanding of how the compiler interprets the MACRO definition, which will eventually explain how a NULL pointer is not actually being dereferenced.

EDIT: Even though other questions answered my query, they dindt make sense to me, as pointed out in the original post. The answer by @dasblinkenlight sheds light on the exact problem I had with ansers to other questions i.e how is it that we're not actually dereferencing the pointer .

Competency answered 11/4, 2016 at 1:55 Comment(3)
What more do you need than this answer? https://mcmap.net/q/20498/-how-does-the-c-offsetof-macro-work-duplicateBellew
Possible duplicate of How does the C offsetof macro work?Bellew
If a is a pointer to address 1234, and b is a member of a at offset 12, then what is &a->b? Now, if a points to address 0, what is &a->b? How did you work that out in your head without dereferencing a?Adhern
F
9

Particularly, the dereferencing of NULL to obtain the offset of the member in the structure.

There is no dereferencing of the pointer going on, because the effect of operator -> are undone by the operator &:

  • This would be a dereference of NULL: ((TYPE *)0)->MEMBER
  • Adding & in front of it makes it an address computation: &((TYPE *)0)->MEMBER

Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.

Consider this example as an illustration:

int a;
int *p = &a;
int b = *p;     // <<== This is a dereference
int *q = &(*p); // <<== This is not a dereference

The two operators, * and &, undo the effect of each other. Operator -> is a "syntactic sugar" on top of * and ., so & can undo its effects as well.

When a compiler sees an expression somePointer->a it takes the numeric value of the pointer somePointer, adds the offset of member a, and learns the place in memory on which you can operate. There are three things you could do to a place in memory:

  1. Read it
  2. Write it
  3. Learn its address

Items 1 and 2 (reading and writing) constitute dereferencing. Item 3, however, is not dereferencing, because the memory at the specific address is not accessed.

The macro essentially asks the compiler to compute the address of member a assuming that the base address is zero. The address of a returned would naturally be equal to a's offset. All you need to do is take its address, which is what you do with the operator &.

Fried answered 11/4, 2016 at 2:2 Comment(3)
This makes sense. I tried the following and the explanation you provided is right: int *b = NULL; printf("\nAddress of b is %p \n",&(*b)); //NO SEGFAULT printf("\nAddress of b is %p and val is %d\n",&(*b), *b); //SEG FAULTCompetency
@Adam Martin Thanks for the link, it provides details on exactly what I was looking for.Competency
Your edit made it even more clearer. This is the explanation I was hoping to find.Competency

© 2022 - 2024 — McMap. All rights reserved.