Usage of C++ NULL vs 0

C

Chris Thomasson

But you can't check whether a pointer is valid; you just have to
know. (I agree that it would be nice if pointers had an
isValid() member function, but they don't.)

What would an `isValid()' function be checking for exactly? If the pointer
is NULL, if the pointer points to an object which exists in non-freed
memory, or all of that? Would it be similar to the following obsolete Win16
functions:

IsBadCodePtr()
IsBadReadPtr()
IsBadStringPtr()
IsBadWritePtr()

AFAICT, in a multi-threaded environment any "isValid" function which works
on pointers has some associated race-conditions. For instance, if Thread A
calls `isValid()' on pointer P which succeeds, and Thread B immediately does
something which invalidates P, well, Thread A will operate on the false
assumption that P is valid when B just invalided it under its nose; that
would be bad.
 
J

James Kanze

What would an `isValid()' function be checking for exactly?

That you can legally dereference the pointer, without risk of
undefined behavior, etc.
If the pointer is NULL, if the pointer points to an object
which exists in non-freed memory, or all of that? Would it be
similar to the following obsolete Win16 functions:
IsBadCodePtr()
IsBadReadPtr()
IsBadStringPtr()
IsBadWritePtr()

Good point. I'd say that isValid() on a non-const pointer means
that you can legally write or read; on a pointer to const, only
that you can read.
AFAICT, in a multi-threaded environment any "isValid" function
which works on pointers has some associated race-conditions.

:). Don't bring threading into it, at least not until we have
a solution for non-threaded code. I'm willing to bet that
either the Win16 functions were very slow, or they gave wrong
results. (With garbage collection, you could sort of do it
fairlly rapidly, at least on most architectures. But even then,
I think there'd be some false positives unless you used some
sort of fat pointers.)
For instance, if Thread A calls `isValid()' on pointer P which
succeeds, and Thread B immediately does something which
invalidates P, well, Thread A will operate on the false
assumption that P is valid when B just invalided it under its
nose; that would be bad.

Yep. It's up to the user to ensure atomicity or protection,
when he needs it. Just like everywhere else.
 
M

Matthias Buelow

Bo said:
Having just a small hammer and a screwdriver makes it simpler to
master one's tools. A skilled craftsman ("knowing what he is doing"),
can be much more productive with a nail gun or a chain saw.

However, a skilled craftsman knows when to use a chainsaw and when to
use a nail file.
 
R

.rhavin grobert

I don't know what the latest standard says, but it at least used to be true
that in C NULL was ((void *)0) At least on some systems. This is illegal
in C++.

What makes this expression illegal? Looks like a pretty good way to
distinguish an integer from a pointer for the compiler...

-.rhavin;)
 
J

Joe Greer

What makes this expression illegal? Looks like a pretty good way to
distinguish an integer from a pointer for the compiler...

-.rhavin;)

Probably the wrong choice or words, but the standard defines NULL to be 0
therefore it would be nonconformant if it were (void *)0.

joe
 
J

James Kanze

The C++ standard makes it clear that ((void *)0) as NULL is a
no-go. Why, because void * to T * is an implicit conversion
in C but is not in C++. Forcing casts on every use of NULL is
not a reasonable request. Blah blah.

It's not quite that simple. The C++ standard makes it clear
that ((void*)0) is not a null pointer constant, and the C
standard makes it clear that it is. But null pointer constants
are special cases. Compiler magic, in sum. And the standard
could literally do anything here.

Note that in C, the following is not guaranteed:

int i0 = 0 ;
void* p = (void*)i0 ;
assert( p == ((void*)0) ) ;

The conversion of a null pointer constant is a special case, and
obeys different rules than other conversions. Historically, the
null pointer constant is 0, going back to B. Why Kernighan and
Richie didn't introduce a special keyword for it, when he
introduced typing (going from B to C), I don't know; the use of
0 was obviously "wrong" even back then. (They probably meant
to, but didn't get around to it until it was too late.) Given
the estabilished use of 0, why the standards (C or C++) allowed
other things (like (1-1) or 0UL---or in the case of C,
((void*)0)) is also beyond me. If they were going to change
something (from just 0), they should have introduced a keyword.
 
J

James Kanze

However, a skilled craftsman knows when to use a chainsaw and
when to use a nail file.

A skilled craftsman also knows the difference between a hammer
and a screwdriver. Or between a pointer and a bool, in the case
at hand.
 
M

Matthias Buelow

James said:
I don't know; the use of
0 was obviously "wrong" even back then.

K&R come from a strong theoretical background; using the value 0 for
invalid pointers is perfectly fine and elegant -- certainly nicer than
fumbling about with special clunky "nullptr" verbosity. That is, unless
you come across a platform where pointers cannot be initialized to all
bits zero. However, imho, one should rather keep the language clean than
embellish it in dubious ways just to acommodate weird architectures. So
augmenting the language to allow interpreting 0 as not-all-bits-zero on
some platforms is a perfectly sound choice, imho, and seems to be the
minimal change necessary to support those environments. If you don't
like it, don't use these architectures. :)
 
M

Matthias Buelow

Bo said:
But it doesn't answer the question that the second one would (if it
was available):

T* p = new T();
delete p;

if (p.isValid())
{
// p still points to a valid object
}

Another example:

T *p;
// is p initialized?

At least most compilers warn of uninitialized variables. However, why
isn't it initialized to some sensible value (like 0)? This is another
example, where C++' claim to be a high-level language just doesn't match
reality. You can either live with it being a macro assembler (just like
C) with considerably more icing on top (compared to C), or delude
yourself and run into problems all the way. I prefer the first approach
and it works reasonably well under that assumption. Botching it with
isValid() and similar hacks trying to give it the appearance of being
anything but a macro assembler won't work, imho.
 
M

Matthias Buelow

James said:
A skilled craftsman also knows the difference between a hammer
and a screwdriver. Or between a pointer and a bool, in the case
at hand.

The fundamental flaw of bool is that one can't map n-ary logic onto the
binary Boolean one. I often had to change bool to something else in
function returns because all of a sudden, I had to return more than just
true/false and still check for truth. Thankfully that still works in
C++. IMHO, bool is just useless.
 
I

Ian Collins

Matthias said:
Another example:

T *p;
// is p initialized?

At least most compilers warn of uninitialized variables. However, why
isn't it initialized to some sensible value (like 0)?

Isn't that why we declare and initialise our variables when we need them?
 
I

Ian Collins

Matthias said:
The fundamental flaw of bool is that one can't map n-ary logic onto the
binary Boolean one. I often had to change bool to something else in
function returns because all of a sudden, I had to return more than just
true/false and still check for truth. Thankfully that still works in
C++. IMHO, bool is just useless.

Maybe C++ could borrow from PHP and have an === (exactly equal to)
operator? Then we could return true, false or NULL.
 
B

Bo Persson

Matthias said:
Another example:

T *p;
// is p initialized?

At least most compilers warn of uninitialized variables. However,
why isn't it initialized to some sensible value (like 0)?

Benchmarks! :)

The blessing and the curse of C++ is C compatibility. If C++ were to
initialize variables where C is not, we would be flooded with silly
benchmarks showing that C code is faster than identical C++. And they
would be right!
This is
another example, where C++' claim to be a high-level language just
doesn't match reality. You can either live with it being a macro
assembler (just like C) with considerably more icing on top
(compared to C), or delude yourself and run into problems all the
way. I prefer the first approach and it works reasonably well under
that assumption.

C++ is a pragmatic way of creating a powerful high level language.
It's inheritance is what made it take off.

I have used other languages like Simula, Modula-2/3, and Ada. Quite
nice for their time, but never really took of. Not even with billions
in fundings, like in the last case.
Botching it with isValid() and similar hacks
trying to give it the appearance of being anything but a macro
assembler won't work, imho.

I am not asking for that either. The C++ solution (to mostly
everything) is to put the pointer in a managing class. The manager
will know and/or make sure that the pointer is valid.


Bo Persson
 
A

anon

Matthias said:
minimal change necessary to support those environments. If you don't
like it, don't use these architectures. :)

Sometimes you do not have a choice (unless you wanted to change a job ;) )
 
A

ajonesfl

I understand NULL is a macro and defined to 0. But for readibility
purpose should
we use NULL for poiner. and 0 for integer.

Also since system provide NULL to be defined to some value(today it is
0) and if
tomorrow the defined value changes, then still our code will be
portable
if we use NULL. So I think instead of using hard coaded value 0, we
should
use NULL for pointer. It increases both for readbility and
portability. Any suggestion?

To answer your questions concerning using NULL or 0, I would agree
with the the creator of the language Bjarne Stroustrup. He mentions
this specifically in his book The C++ Programming Language in section
5.1.1 and again in section 5.8. His advice is "Use 0 rather than
NULL". This is a direct quote from his book. If you read section 5.1.1
he explains why....

-Adam J.
 
C

Chris Thomasson

J

James Kanze

K&R come from a strong theoretical background;

K&R were adapting B to support types, since some sort of typing
is needed on a byte addressable architecture (at least if you
are to use byte addressing). B was totally untyped. And there
was never the least bit of "theoretical" in C; C is a succession
of ad hoc solutions to problems that were actually encountered.
using the value 0 for invalid pointers is perfectly fine and
elegant -- certainly nicer than fumbling about with special
clunky "nullptr" verbosity. That is, unless you come across a
platform where pointers cannot be initialized to all bits
zero.

I've worked on platforms where all zero bits were valid
pointers. At least by the time they'd published, K&R made it
quite plain that using 0 for pointers was a hack, and that it
required some fancy games with the type system to make it work.

But that's a different problem. We're talking about using a
pointer where a boolean value is required. In a typed language:
a conversion. In a strongly typed language, implicit
conversions are an anathema. So the question really boils down
to whether you want strict static typing or not (or rather, to
what degree, because of course, it's not a black and white
question). In this regard, I agree with the original
proposition for adding a bool type: all of the implicite
conversions to bool should have been deprecated from the start.
The long term evolution of C++ is striving to increase static
type safety. (Note that Stroustrup was responsible for large
scale development, or something like that, at Bell Labs. The
larger the project, the more important static type checking
becomes.)
 
J

James Kanze

[...]
C++ is a pragmatic way of creating a powerful high level
language. It's inheritance is what made it take off.

It's its pragmatics (C compatibility, works with existing
linkers, etc.) which made it succeed. It certainly wasn't the
only (or even the first) language to propose inheritance.
I have used other languages like Simula, Modula-2/3, and Ada.
Quite nice for their time, but never really took of. Not even
with billions in fundings, like in the last case.

In the last case, the language probably didn't take of because
of the funding, or the source of the funding. I know of one or
two cases where Ada wasn't considered because it was backed by a
government burocracy.
 
N

Nick Keighley

James Kanze wrote:

The fundamental flaw of bool is that one can't map n-ary logic onto the
binary Boolean one.

The fundamental problem of int is that one can't map floating point
values
onto the integral Integer ones

I often had to change bool to something else in
function returns because all of a sudden, I had to return more than just
true/false and still check for truth.

this very rarely happens to me. I think you are misusing bool.
I use bool for predicates so my bool funnctions are called things like

is_valid(), is_used(), has_hit(), empty(), equal(), event_occurred()
etc.

Thankfully that still works in C++.

what works in C++?

IMHO, bool is just useless.

it's just find for representing booleans
 
J

James Kanze

The fundamental flaw of bool is that one can't map n-ary logic
onto the binary Boolean one.

Which is why we have a type bool, and operators which explicitly
return a bool.
I often had to change bool to something else in function
returns because all of a sudden, I had to return more than
just true/false and still check for truth.

But what is the truth, in such cases? You've radically changed
the contract of a function. The last thing you want is for
existing client code to compile without change; you want to be
forced to look at that code, to ensure that it will still work
with the new contract.
Thankfully that still works in C++.

Just the opposite. You've just set forward an incredibly strong
argument against the implicit conversion of bool. One that
hadn't occurred to me (because I generally don't allow myself
the liberty of changing the contract of a function, once it is
used in client code).
IMHO, bool is just useless.

But you just proved the contrary.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top