[svlug] Structure Field Offset Measurement

J C Lawrence claw at kanga.nu
Fri Jan 5 23:32:02 PST 2001


On Fri, 5 Jan 2001 15:58:56 -0800 
Karen Shaeffer <shaeffer at best.com> wrote:

> On Fri, Jan 05, 2001 at 12:11:16AM -0800, J C Lawrence wrote:
>> That's not the problem.  The problem is that NULL is a special
>> value, which is given special recognition under ANSI.  The
>> semantic requirements of NULL are that it must be a legal value
>> for a pointer to any data type, no more.

> OK, first, thanks for your comments J C, they are always
> interesting and thought provoking. Randy pointed out the MACRO
> explicitly casts 0, so NULL is not part of the evaluation, and Ian
> noted the MACRO is defined as part of the standard.

Not to cut too fine a point on it, Randy is wrong in this case.  The
casting of z literal zery to a pointer type makes it a NULL.  It is
just that simple.

As happens however my copy of the X3J11 spec is buried in a box
right now, and I only have X3J14 out.  Is that exact implementation
of offsetof() defined by the spec, or is it provided as a possible
implementation?  I'd be extremely surprised if they did anything but
give it as a possible implementation.

> Switching gears to the NULL MACRO, you are correct on that
> point. Let's limit the focus to Linux. Looking back into
> /usr/include/linux/stddef.h, we see the following:

> <quote> #undef NULL #if defined(__cplusplus) #define NULL 0 #else
> #define NULL ((void *)0) #endif </quote>

> Noting it is not mandated by the c standard, the implementation
> here does define NULL as all-bits zero. 

Actually the header file does explicitly __NOT__ do this.  Under
ANSI for C and C++ a literal zero in a pointer context at compile
time is to be translated by the compiler into that platform's
definition of NULL.  If that platform's definition of NULL happens
to be a value which is not all-bits-zero, then both the above
#defines will result in values which are not all bits zero AT
COMPILE TIME.

This is both expected and necessary behaviour.

It is for this reason that the following code will print "Surprise!"
on some platforms:

  char **ppc = (char **)calloc (5);
  if (ppc[2]) {
    printf ("Surprise!")
  }

or

  char **ppc = (char **)malloc (5);
  memset (ppc, 0, 5 * sizeof (char*));
  if (ppc[2]) {
    printf ("Surprise!")
  }


But the following never will because the compiler will translate the
literal zero in a pointer context to the host's representation of NULL:

  char **ppc = (char **)calloc (5);
  if (ppc[2] == (char *)0) {
    printf ("Surprise!")
  }

or

  char **ppc = (char **)malloc (5);
  memset (ppc, (char *)0, 5 * sizeof (char*));
  if (ppc[2]) {
    printf ("Surprise!")
  }

The spec is extremely clear on this point.  The compl.lang.c FAQ
also deals with this area at some length and detail.

> I haven't checked all ports of Linux, but I speculate this is so
> for *all* Linux ports. Comments?

It is possible (I don't know) that the recent S360 port is an
exception.  I know that several mainframes have very interesting
memory models (I spent some time working on S390s under VM and TSO,
which was kinda interesting, but didn't get into it far enough to
really grom the memory model which was far from "standard" -- its
Burroughs that get really interesting).

Heck, next you'll be telling me that all bytes have 8 bits.

-- 
J C Lawrence                                       claw at kanga.nu
---------(*)                          http://www.kanga.nu/~claw/
--=| A man is as sane as he is dangerous to his environment |=--




More information about the svlug mailing list