Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sizeof NULL

1 view
Skip to first unread message

Dan Pop

unread,
Jan 28, 2004, 10:52:44 AM1/28/04
to
Is sizeof NULL a correct expression in C? If not, what is the chapter and
verse it violates?

If sizeof NULL is a correct expression, then NULL cannot be defined as
(void *)0, because the expansion sizeof (void *)0 will be actually
parsed as (sizeof(void *)) 0 which is not a correct expression, so NULL
would have to be defined like this:

#define NULL ((void *)0)

but then, it is not clear whether ((void *)0) is still a null pointer
constant...

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Wojtek Lerch

unread,
Jan 28, 2004, 12:36:44 PM1/28/04
to
"Dan Pop" <Dan...@cern.ch> wrote in message
news:bv8lsc$am2$1...@sunnews.cern.ch...

> Is sizeof NULL a correct expression in C? If not, what is the chapter and
> verse it violates?

It is. 7.1.2#5:

Any definition of an object-like macro described in this clause shall expand
to code that is
fully protected by parentheses where necessary, so that it groups in an
arbitrary
expression as if it were a single identifier.

Jeremy Yallop

unread,
Jan 28, 2004, 12:43:34 PM1/28/04
to
Dan Pop wrote:
> Is sizeof NULL a correct expression in C?

Yes. The relevant text is:

5 Any definition of an object-like macro described in this clause


shall expand to code that is fully protected by parentheses where
necessary, so that it groups in an arbitrary expression as if it

were a single identifier. (7.1.2)

This means that ((void *)0) is a valid definition for NULL, but (void *)0
is not, as your example shows. Here's another program where the
parentheses make a difference:

#include <stddef.h>

int main()
{
int a[1];
char *p = NULL[a];
}

This program requires a diagnostic if NULL is defined as '0' or
'((void *)0)' (although the reason for the diagnostic is different in
each case). If NULL were defined as '(void *)0' no diagnostic would
be required.

Jeremy.

Stefan Farfeleder

unread,
Jan 28, 2004, 2:43:38 PM1/28/04
to
On 2004-01-28, Dan Pop <Dan...@cern.ch> wrote:
> Is sizeof NULL a correct expression in C? If not, what is the chapter and
> verse it violates?

> If sizeof NULL is a correct expression, then NULL cannot be defined as
> (void *)0, because the expansion sizeof (void *)0 will be actually
> parsed as (sizeof(void *)) 0 which is not a correct expression, so NULL
> would have to be defined like this:

> #define NULL ((void *)0)

> but then, it is not clear whether ((void *)0) is still a null pointer
> constant...

DR 43 asked the same question in 1992. The correction was to add
7.1.2#5:

"Any definition of an object-like macro described in this clause shall
expand to code that is fully protected by parentheses where necessary,
so that it groups in an arbitrary expression as if it were a single
identifier."

--
Stefan Farfeleder

Keith Thompson

unread,
Jan 28, 2004, 2:58:51 PM1/28/04
to
"Wojtek Lerch" <Wojt...@yahoo.ca> writes:
> "Dan Pop" <Dan...@cern.ch> wrote in message
> news:bv8lsc$am2$1...@sunnews.cern.ch...
> > Is sizeof NULL a correct expression in C? If not, what is the chapter and
> > verse it violates?
>
> It is. 7.1.2#5:
>
> Any definition of an object-like macro described in this clause
> shall expand to code that is fully protected by parentheses where
> necessary, so that it groups in an arbitrary expression as if it
> were a single identifier.

So 7.1.2#5 implies that (void*)0 is not a valid definition for NULL,
but ((void*)0) could be -- except that (as Dan points out, and as we
discussed here at length recently), a strict reading of the definition
of a "null pointer constant" excludes ((void*)0). Fascinating.

I know that there are implementations that define NULL as ((void*)0),
which seems perfectly reasonable. The solution, I think, is to fix
the wording in the standard.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"

Barry Margolin

unread,
Jan 28, 2004, 10:30:31 PM1/28/04
to
In article <bv8lsc$am2$1...@sunnews.cern.ch>, Dan...@cern.ch (Dan Pop)
wrote:

> Is sizeof NULL a correct expression in C? If not, what is the chapter and
> verse it violates?

Besides the parenthesis issue you raised, is there any way to make use
of sizeof NULL portably? Doesn't the result depend on whether the macro
expands to an integer zero or one cast to void*, and if it's an integer
zero, which integer type was chosen? Since you can't predict this, how
could the result be at all meaningful?

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Paul Eggert

unread,
Jan 29, 2004, 1:21:04 AM1/29/04
to
At Thu, 29 Jan 2004 03:30:31 GMT, Barry Margolin <bar...@alum.mit.edu> writes:

> Besides the parenthesis issue you raised, is there any way to make use
> of sizeof NULL portably?

Sure. Here's one example:

! sizeof NULL

This is just a fancy way of saying 0, but it's perfectly valid C.

Barry Margolin

unread,
Jan 29, 2004, 1:30:24 AM1/29/04
to
In article <7w65evl...@sic.twinsun.com>,
Paul Eggert <egg...@twinsun.com> wrote:

Do you have any *useful* examples? That's a real degenerate case, that
merely depends on the fact that sizeof <anything> is non-zero. There's
no reason to use NULL there in preference to any other expression. Can
you give a realistic example?

David R Tribble

unread,
Jan 29, 2004, 12:08:56 PM1/29/04
to
Barry Margolin <bar...@alum.mit.edu> writes:
>> Besides the parenthesis issue you raised, is there any way to make use
>> of sizeof NULL portably?

Paul Eggert <egg...@twinsun.com> wrote:
>> Sure. Here's one example:
>> ! sizeof NULL
>> This is just a fancy way of saying 0, but it's perfectly valid C.

Barry Margolin <bar...@alum.mit.edu> wrote


> Do you have any *useful* examples? That's a real degenerate case, that
> merely depends on the fact that sizeof <anything> is non-zero. There's
> no reason to use NULL there in preference to any other expression. Can
> you give a realistic example?

You could use it to determine if the compiler has defined NULL as an integer
constant (i.e., 0) instead of a pointer-typed constant, assuming that
sizeof(int) and sizeof(void*) are different.

But I'm not sure that bit of information is actually useful, either.


The only reason I can think of to use 'sizeof(NULL)' is to allocate space to
store a null pointer somewhere. But then that's the same as determining
the size of a pointer, which is more correctly written as 'sizeof(void*)'.
In fact, using 'sizeof(NULL)' is not portable, breaking on systems where
sizeof(int) and sizeof(void*) are different.

-drt

Christian Bau

unread,
Jan 29, 2004, 3:10:30 PM1/29/04
to
In article <f4002eab.04012...@posting.google.com>,

da...@tribble.com (David R Tribble) wrote:

> The only reason I can think of to use 'sizeof(NULL)' is to allocate space to
> store a null pointer somewhere. But then that's the same as determining
> the size of a pointer, which is more correctly written as 'sizeof(void*)'.
> In fact, using 'sizeof(NULL)' is not portable, breaking on systems where
> sizeof(int) and sizeof(void*) are different.

sizeof(NULL) may be equal to sizeof (int) which may be less than the
size of any pointer.

Casper H.S. Dik

unread,
Jan 29, 2004, 7:14:33 PM1/29/04
to
da...@tribble.com (David R Tribble) writes:

>You could use it to determine if the compiler has defined NULL as an integer
>constant (i.e., 0) instead of a pointer-typed constant, assuming that
>sizeof(int) and sizeof(void*) are different.

#define NULL 0L

(in case sizeof (int) != sizeof (void *) == sizeof (long)

>The only reason I can think of to use 'sizeof(NULL)' is to allocate space to
>store a null pointer somewhere. But then that's the same as determining
>the size of a pointer, which is more correctly written as 'sizeof(void*)'.
>In fact, using 'sizeof(NULL)' is not portable, breaking on systems where
>sizeof(int) and sizeof(void*) are different.

I don't think you can actually store a NULL pointer in "sizeof NULL"
storage; what would you cast it to? And why would you need to store
one anyway?

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

David R Tribble

unread,
Jan 30, 2004, 11:15:57 AM1/30/04
to
David R Tribble writes:
>> The only reason I can think of to use 'sizeof(NULL)' is to allocate space to
>> store a null pointer somewhere. But then that's the same as determining
>> the size of a pointer, which is more correctly written as 'sizeof(void*)'.
>> In fact, using 'sizeof(NULL)' is not portable, breaking on systems where
>> sizeof(int) and sizeof(void*) are different.

Casper H.S. Dik wrote


> I don't think you can actually store a NULL pointer in "sizeof NULL"
> storage; what would you cast it to? And why would you need to store
> one anyway?

I don't think 'sizeof(NULL)' has any practical use (which is what I meant
to imply). And it's not portable anyway, to boot.


<new-topic>

A related, but more interesting, question is the difference between data
pointers and function pointers, especially when:
sizeof(void *) < sizeof(void (*)())

IIRC, ISO C states flat out that all pointers are convertible to 'void*'
and back again without loss of value, but the situation is complicated by
the case above. It might be useful to propose a standard "generic function
pointer type", e.g., 'void (*)()', which is to function pointers what
'void*' is to data pointers.

(I could be wrong about this, and 'sizeof(int*) < sizeof(void*)' could be
allowed for a given implementation; in which case 'void*' and 'void(*)()'
need not be different sizes.)

-drt

P.J. Plauger

unread,
Jan 30, 2004, 11:41:50 AM1/30/04
to
"David R Tribble" <da...@tribble.com> wrote in message
news:f4002eab.04013...@posting.google.com...

> A related, but more interesting, question is the difference between data
> pointers and function pointers, especially when:
> sizeof(void *) < sizeof(void (*)())
>
> IIRC, ISO C states flat out that all pointers are convertible to 'void*'
> and back again without loss of value, but the situation is complicated by
> the case above.

No. Only *object* pointers can be converted to void* and back. Function
pointers are incommensurate.

> It might be useful to propose a standard "generic function
> pointer type", e.g., 'void (*)()', which is to function pointers what
> 'void*' is to data pointers.

No need. *Any* function pointer can hold any other function pointer. Just
be careful not to call through it with the wrong type.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


Christian Bau

unread,
Jan 30, 2004, 6:34:11 PM1/30/04
to
In article <iPvSb.196$9p5...@nwrddc02.gnilink.net>,
"P.J. Plauger" <p...@dinkumware.com> wrote:

> "David R Tribble" <da...@tribble.com> wrote in message
> news:f4002eab.04013...@posting.google.com...
>

> > It might be useful to propose a standard "generic function
> > pointer type", e.g., 'void (*)()', which is to function pointers what
> > 'void*' is to data pointers.
>
> No need. *Any* function pointer can hold any other function pointer. Just
> be careful not to call through it with the wrong type.

In practice, yes. According to the C Standard, kind of. The C Standard
says that you can convert from one function pointer type to another and
back and get the same pointer. It doesn't say what happens when you cast
A->B->C->A.

So yes, if A and B are different function pointer types, then the C
Standard says you can convert from A to B and back, so B must hold all
possible values of A. But more complex conversions are not defined by
the C Standard.

Douglas A. Gwyn

unread,
Jan 31, 2004, 12:43:22 AM1/31/04
to
David R Tribble wrote:
> IIRC, ISO C states flat out that all pointers are convertible to 'void*'
> and back again without loss of value, ...

No, only pointers to objects (data).

> the case above. It might be useful to propose a standard "generic function
> pointer type", e.g., 'void (*)()', which is to function pointers what
> 'void*' is to data pointers.

You don't really need it.

0 new messages