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

Null vs. 0 pointers

2 views
Skip to first unread message

Hawley K Rising

unread,
Jun 3, 1994, 11:35:30 PM6/3/94
to
Is it my imagination or was NULL the (only) pointer to nowhere in C?
Why is it part of the standard in C++ that this be equivalent to 0?
Wouldn't it have been better to leave NULL distinguished since 0 can be
valid in some environments as an address, and this leaves a valid address
unaddressable in C++? It isn't possible within the confines of the
language to have only some of the values be valid addresses and others
distinguished values, so this does in fact invalidate the address. It's
also impossible to overload the operators on pointers, so machine
dependent workarounds must go outside the language. Other than
convenience (being able to say if(!ptr) ) was there another reason?

Hawley Rising
ris...@crl.com

Matt Austern

unread,
Jun 4, 1994, 2:20:16 AM6/4/94
to
In article <2sosq2$p...@crl2.crl.com> ris...@crl.com (Hawley K Rising) writes:

> Is it my imagination or was NULL the (only) pointer to nowhere in C?
> Why is it part of the standard in C++ that this be equivalent to 0?

Contrary to popular belief, there is no NULL pointer in either C or
C++. In both languages, NULL is just a macro defined in one of the
standard header files, which, in fact, is usually just defined to
expand to 0.

In both languages, the integer constant 0 means (in a pointer context)
a pointer that does not point to any valid object. It does not
necessarily mean the machine address 0.

Whether you want to use 0 or NULL is purely a matter of style;
different people have different preferences. As long as you use
one style constistently, you should be fine.

All that's really happened with C++ is that the style of using 0,
instead of NULL, is more common in C++ than it is in C. I suspect
that the main reason for this is that K&R recommends using NULL, while
Stroustrup recommends using 0.

--
Matt Austern "Se non e vero, e ben trovato"

Mike Young

unread,
Jun 3, 1994, 9:22:17 PM6/3/94
to
In article <MATT.94J...@physics2.berkeley.edu> ma...@physics2.berkeley.edu (Matt Austern) writes:
>From: ma...@physics2.berkeley.edu (Matt Austern)
>Subject: Re: Null vs. 0 pointers
>Date: 04 Jun 1994 06:20:16 GMT


>In both languages, the integer constant 0 means (in a pointer context)
>a pointer that does not point to any valid object. It does not
>necessarily mean the machine address 0.

Yes, but I think the original poster was asking about architectures where 0 IS
a valid address. This address is not addressable if we define 0 to be the
invalid pointer. I don't know of any, but this was the question.

Mike.

Matt Austern

unread,
Jun 4, 1994, 2:48:05 AM6/4/94
to
In article <mikey.76...@mcs.com> mi...@mcs.com (Mike Young) writes:

> >In both languages, the integer constant 0 means (in a pointer context)
> >a pointer that does not point to any valid object. It does not
> >necessarily mean the machine address 0.
>
> Yes, but I think the original poster was asking about architectures
> where 0 IS a valid address. This address is not addressable if we
> define 0 to be the invalid pointer.

Yes it is. The *integer constant* 0, in a pointer context, is
converted to a pointer that doesn't point to any valid object. You
can access address 0 by using 0 in a way such that it is not an
integer constant. (Assuming, of course, that you're working on a
machine where a physical address is described by a single integral
value, and that you can access any particular address by casting an
int to a pointer.) For example:
int i;
char* p;
i=0;
p = (char*) i;
Note, further, that if you write "p = 0", p will not necessarily have the
same value as if you write "p = (char*) i".

Finally, this is the same in C++ as in C; the two languages just
aren't very different as far as the null pointer is concerned. In
both languages, it's really more a question of stylistic preferance
than anything else.

I think that this question is discussed in detail in the comp.lang.c
FAQ list. It's probably a good idea to read the discussion there.

Hawley K Rising

unread,
Jun 5, 1994, 8:31:36 PM6/5/94
to
Mike Young (mi...@mcs.com) wrote:

: Yes, but I think the original poster was asking about architectures where 0 IS

: a valid address. This address is not addressable if we define 0 to be the
: invalid pointer. I don't know of any, but this was the question.

Yes, this was the intent of my posting, that in this one and perhaps only
one instance a VALUE which could have differing meanings on different
machines is designated as a specific meaning. I was trying to say that
IMHO the language STANDARD should specify the existence of the macro NULL
with the appropriate properties, as being the pointer which does not
point to anything, since 0 is in the address space, and every other value
in the address space is treated as an address which can be a pointer. On
my machine 0 is valid in some circumstances, -1L never is, if the
standard said that -1L was the pointer that pointed nowhere, the point
would be easier to make.

The question is about the standard, I know how the language is
implemented and how to use it -- meaning it belongs here.

Hawley Rising
ris...@crl.com

Steve Clamage

unread,
Jun 6, 1994, 4:14:19 PM6/6/94
to
In article n...@crl2.crl.com, ris...@crl.com (Hawley K Rising) writes:
> ... I was trying to say that
>IMHO the language STANDARD should specify the existence of the macro NULL
>with the appropriate properties, as being the pointer which does not
>point to anything, since 0 is in the address space, and every other value
>in the address space is treated as an address which can be a pointer.

If I understand you, you want the language standard to say that you
can specify an integer value for an address. This would imply that
the address of any object (and perhaps function as well) can be
represented as an integer.

There are plenty of machines for which this is not possible. For example,
virtual addresses might require more bits than are available in any
integer type. (This is allowed, and there are machines like this.)
Also, some machines have extra bits in pointers specifying capabilities,
types, permissions, and so on. Even if some integer type is big enough
to hold all the bits, such machine architectures don't let you access
the special bits by reading or storing in the normal way.

It just isn't practical to demand in the C++ language standard any sort
of correspondence between integers and pointers. It would rule out
certain machines (users could not get a conforming compiler), for one thing.
For another, use of machine addresses is not going to be portable from
one kind of machine to another, or even across different operating systems
on the same machine. So what is gained by the requirement?

Finally, if on a particular machine there is a one-to-one correspondence
between some integer type and pointers, the compiler will usually allow
casts to work as you would expect -- often the feature will be explicitly
documented. Such extensions are allowed by the C standard, and will be
allowed by the C++ standard.

The language standard specifies (in particular) what must work
portably across all implementations. Pointer-integer equivalence is
not one of those things. Implementations are allowed to let such
equivalence work, and ususally do on systems where it makes sense.
---
Steve Clamage, stephen...@eng.sun.com

Bjarne Stroustrup

unread,
Jun 6, 1994, 3:12:52 PM6/6/94
to

ris...@crl.com (Hawley K Rising @ CRL Dialup Internet Access (415) 705-6060 [login: guest]) writes

> Is it my imagination or was NULL the (only) pointer to nowhere in C?

It is your imagination. In K&R C and in ISO C you can spell the value
you call NULL 0 or 2-2 or ~-1.

> Why is it part of the standard in C++ that this be equivalent to 0?

because C++ inherited the C rule.

John Max Skaller

unread,
Jun 6, 1994, 1:20:00 PM6/6/94
to
In article <mikey.76...@mcs.com> mi...@mcs.com (Mike Young) writes:

I dont quite know what you mean but on the 486:

in real mode: 0000:0000 is a valid machine address,
which is a pain because it accesses the interrupt vector table,
not a good thing if your C program has bugs and choses 0000:0000
as NULL: regularly causes machine crashes.

in protected mode, segment selector 0000 is a valid
selector but refers to no memory so it can be loaded into a segment
register and any attempt to use it to access memory causes a protection
violation.

So: the 486 covers both cases :-)
And in _neither_ case is it an "invalid" address.
So it depends what you mean by a "valid" address :-)


--
JOHN (MAX) SKALLER, INTERNET:max...@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA

m...@minster.york.ac.uk

unread,
Jun 7, 1994, 6:21:00 AM6/7/94
to
In article <MATT.94J...@physics2.berkeley.edu>,

Matt Austern <ma...@physics.berkeley.edu> wrote:
>
>Contrary to popular belief, there is no NULL pointer in either C or
>C++. In both languages, NULL is just a macro defined in one of the
>standard header files, which, in fact, is usually just defined to
>expand to 0.

The existence of a macro NULL with the value 0 is not mentioned in the
Annotated C++ Reference Manual, or the C++ Programming Language, 2nd ed.
as far as I can see. Has NULL actually been added to the language
definition, or do people assume its existence because it usually
gets defined by the C header files they use?

>All that's really happened with C++ is that the style of using 0,
>instead of NULL, is more common in C++ than it is in C. I suspect
>that the main reason for this is that K&R recommends using NULL, while
>Stroustrup recommends using 0.

Are you sure it's not because NULL is not part of the language?

-Mark.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Mark H. Wilkinson <m...@minster.york.ac.uk> : Research student in user
University of York, England : interface management systems

Brian Hook

unread,
Jun 7, 1994, 11:17:07 AM6/7/94
to
In article <7709844...@minster.york.ac.uk> m...@minster.york.ac.uk writes:
> >All that's really happened with C++ is that the style of using 0,
> >instead of NULL, is more common in C++ than it is in C. I suspect
> >that the main reason for this is that K&R recommends using NULL, while
> >Stroustrup recommends using 0.

> Are you sure it's not because NULL is not part of the language?

Please cf. "Design and Evolution of C++" by B. Stroustrup, which addresses
this (and many other) subjects.

For one, NULL, as far as I know, has no "standard" definition, it's just
assumed to exist in many include files. Hell, my "stdio.h" doesn't have a
prototype for printf()!

Another problem is that some compilers (Microsoft C?) define NULL as:

#define NULL (void *)0

which causes some problems with C++ (where "casting is not our friend"),
not to mention problems assigning NULL to a non pointer type (which, for
some reason, a lot of existing code does).

Finally, the "C++" way of doing things, i.e. using a const definition,
wouldn't be applicable since NULL can mean so many different things and
thus C++'s hardcore type checking would actually pose a problem. When you
just use "0" you are letting the compiler determine by context what 0
means. When you use "const void *NULL = 0;" you are limited to assigning
NULL to void pointers without having a (cautious) compiler complain.

I'm sure I've made a mistake somewhere in here, and I'm sure I'll be
corrected. Carry on.

Brian

--
+---------------------------------------------------------------------+
| Brian Hook | Specializing in real-time 3D graphics |
| Box 90315 |---------------------------------------------|
| Gainesville, FL 32607 | b...@prl.ufl.edu |
+- "Style distinguishes excellence from accomplishment" - J. Coplien -|

Barry Margolin

unread,
Jun 7, 1994, 3:46:23 PM6/7/94
to
In article <2sosq2$p...@crl2.crl.com> ris...@crl.com (Hawley K Rising) writes:
>Wouldn't it have been better to leave NULL distinguished since 0 can be
>valid in some environments as an address, and this leaves a valid address
>unaddressable in C++? It isn't possible within the confines of the
>language to have only some of the values be valid addresses and others
>distinguished values, so this does in fact invalidate the address.

Hardly. Any mechanism to allow you to specify a specific location for a
pointer must be an implementation extension, since neither C nor C++
specifies a standard way to do this. So that extension could easily
provide a way to make a pointer to location 0, e.g.

int *null_ptr = 0; // null pointer
int *zero_ptr = _make_ptr(0); // pointer to location zero

or

int *zero_ptr = -1; // confusing, but a valid extension

Maybe even:

int *zero_ptr = 0.0;

if the language doesn't require an error in this case.

Of course, with an implementation where C/C++ pointers have the same
representation as machine addresses and all addresses are valid, there will
have to be some valid address that compares equal to the null pointer.
However, you'll have to use implementation-specific mechanisms to get such
pointers (i.e. they should never be returned by the standard new, malloc(),
or &), and the programmer should know not to bother comparing pointers that
may have been assigned that way against the null pointer.

Note also that the address that matches the null pointer isn't
"unaddressable". The language simply doesn't specify the results of
dereferencing such a pointer. But since you have to use
implementation-specific means to create such a pointer, you should be
comfortable with the implementation-specific results of dereferencing it.
--
Barry Margolin
System Manager, Thinking Machines Corp.

bar...@think.com {uunet,harvard}!think!barmar

Warner Losh

unread,
Jun 7, 1994, 3:23:35 PM6/7/94
to
In article <2t002r$3...@engnews2.Eng.Sun.COM> cla...@taumet.Eng.Sun.COM writes:
>The language standard specifies (in particular) what must work
>portably across all implementations. Pointer-integer equivalence is
>not one of those things. Implementations are allowed to let such
>equivalence work, and ususally do on systems where it makes sense.

True, however, there is verbage to the effect that if you convert a
pointer to an integer (AND there are enough bits in that integer to
contain the pointer) and then back to a pointer of the same type, then
the unconverted and the converted points will be identical. While
this isn't pointer integer equivalence, it does specify a well defined
mapping when no truncation would occur.

Warner
--
Warner Losh i...@boulder.parcplace.COM ParcPlace Boulder
"... but I can't promote you to "Prima Donna" unless you demonstrate a few
more serious personality disorders"

Barry Margolin

unread,
Jun 10, 1994, 2:41:17 PM6/10/94
to
In article <Cr1KJ...@boulder.parcplace.com> i...@boulder.parcplace.com (Warner Losh) writes:
>True, however, there is verbage to the effect that if you convert a
>pointer to an integer (AND there are enough bits in that integer to
>contain the pointer) and then back to a pointer of the same type, then
>the unconverted and the converted points will be identical. While
>this isn't pointer integer equivalence, it does specify a well defined
>mapping when no truncation would occur.

No, it doesn't specify a well-defined ptr->integer or integer->ptr mapping,
only a property that ptr->integer->ptr must have. The two one-way mappings
must be inverses of each other, but that doesn't mean that they must do
what you expect intuitively (turn the integer N into a pointer to address
N). Here's a perfectly valid implementation:

template<class T> class ptr_converter {
T** ptr_table;
long table_size;
long cur_entry;
public:
long ptr_to_integer(T *);
T *integer_to_ptr(long);
ptr_converter(): ptr_table(malloc(100*sizeof(T*))), cur_entry(0),
table_size(100) {}
~ptr_converter() { free(ptr_table); }
}

template<class T> long ptr_converter<T>::ptr_to_integer (T* ptr) {
if (cur_entry >= table_size) {
table_size = 2*table_size;
ptr_table = (void**)realloc(table_size * sizeof(T *));
}
ptr_table[cur_entry] = ptr;
return cur_entry++;
}

template<class T> T* ptr_converter<T>::integer_to_ptr (long integer) {
if (integer < 0 || integer >= cur_entry) {
// raise error
} else {
return ptr_table[integer];
}
}

I actually once half-heartedly suggested that Symbolics use an
implementation like this in their Lisp Machine C compiler. It's currently
unable to do ordinary ptr<->integer conversions because it implements
pointers as references to Lisp objects, which may be moved by the garbage
collector, so a simple numeric address wouldn't work. They simply give up
on it, treating it as if there's no integer type large enough.

Ross Ridge

unread,
Jun 11, 1994, 10:54:11 PM6/11/94
to
Matt Austern <ma...@physics.berkeley.edu> wrote:
>Contrary to popular belief, there is no NULL pointer in either C or
>C++. In both languages, NULL is just a macro defined in one of the
>standard header files, which, in fact, is usually just defined to
>expand to 0.

<m...@minster.york.ac.uk> wrote:
>The existence of a macro NULL with the value 0 is not mentioned in the
>Annotated C++ Reference Manual, or the C++ Programming Language, 2nd ed.
>as far as I can see.

It is mentioned indirectly. r2.4 reads:

Certain implementation-dependent properties ... are defined in
the standard header files ... <stddef.h> These header files
are part of the ANSI C standard.

The ANSI C standard requires that NULL be defined in <stddef.h> and so
the C++RM does also.

What the current working papers might say about the subject, I dunno.

Ross Ridge

0 new messages