But, when we are not doing any read/write from that address, then why
do we need to dereference it all ? I don't know much about what C
standard says about that. I tried many times reading it, but the
language used by the standard is too difficult to understand for a
beginner ( although I have been leraning C for the past 3 years, still
I am no better than a newbie). Coming back to the question, its very
hard for me to find out any reason why the C standard imposes this
restricion that the pointer may be dereferenced while finding the
address of some member ? I am not fetching or storing anything at that
address. Shouldn't this be a simple pointer arithmetic ?
Let's look at a typical (I think) definition of offsetof:
#define offsetof(s, m) (size_t)(&(((s *)0)->m))
and consider the sequence of operations that this specifies.
0 Zero
(s *)0 A null pointer of type pointer-to-s
((s *)0)->m The value of the member "m" of the object
of type "s" obtained by dereferencing the
null pointer
&(((s *)0)->m) No, we just need the address, not the value.
(size_t)(&(((s *)0)->m)) Convert the address to size_t
Now any reasonable compiler is very likely to optimize out the
evaluation of the value of the (nonexistent) structure member m. The
point is that the standard doesn't bother to *mandate* this particular
optimization. Similarly, it doesn't require a compiler to optimize
away the evaluation of x in (x * 0).
And the fact that the standard doesn't mandate this particular
optimization (that it allows the value of the member to be evaluated
and discarded) doesn't cause many problems in practice. The only good
reason I can think of to write code like the above is to implement
something like offsetof -- but you don't need to, because it's already
implemented for you. (As I'm sure you know, the author of the
<stddef.h> header is allowed to make whatever implementation-specific
assumptions he likes, as long as everything works as specified for
that implementation.)
Also, what I believe that it is only compiler that can tell about the
offset of some member in some structure. So, why not add one more
operator "offsetof" just as we have "sizeof" operator ?
It's probably just for historical reasons. My guess is that, many
years ago, somebody decided that it would be useful to determine the
offset of a structure member, and came up with something like the
above macro. This must have been before C was standardized, and the
author freely made assumptions about the behavior of the compiler. It
wasn't necessary to add a new keyword to the language. When the
language was standardized, it was felt that the simplest thing to do
was to bless the already existing offsetof() macro -- but since it
can't be implemented portably (given the language rules of the new
standard), the committee only required that it be possible to
implement it in *some* way.
If the usual definition of offsetof() doesn't work for a given
compiler, for whatever reason, the implementers can alway define and
use some compiler magic:
#define offsetof(s, m) __magic_offsetof(s, m)
offsetof() works correctly in all C implementations, and there's no
real need for any programmer to worry about just *how* it works.
There isn't really a problem to be fixed.