Logical Value Of A Pointer

J

James Kanze

Right. Therefore, we are restating that 'a' has a type that
can be compared with a null pointer.

Amongst other things. (Actually, we're not even stating that,
according to the standard.) But that's not the reason we use
it.
But if we have already
defined 'a' as having a pointer type, we know that we can
compare 'a' with a null pointer, so I think we should not
restate that fact in our code if we can reasonably avoid doing
so.

But the purpose of the '== NULL' isn't to state anything about
a: it states what we're comparing it to (and how). A pointer
isn't true or false; it has a (conceptually) infinite number of
possible values. I can compare it to NULL (or 0), or to some
other pointer value.

The implicit conversion of a pointer to bool is a breach in the
type system. In addition, it's a lossy conversion. (But if I
understand your argument correctly, you're not arguing for the
conversion, but rather that "conditions" can take many different
types, and not just bool. Which sounds like an oxymoron to me.)
 
K

Kai-Uwe Bux

James Kanze wrote:
[snip]
(But if I
understand your argument correctly, you're not arguing for the
conversion, but rather that "conditions" can take many different
types, and not just bool. Which sounds like an oxymoron to me.)

That is confusing the definitions of the standard with how one thinks about
language constructs. The implicit conversion are crafted so that

if ( expr ) { ... }

is for all practical purposes equivalent to

if ( expr != 0 ) { ... }

So, one may think about if-clauses as testing for non-zeroness. That the
standard accomplishes this by implicit conversions is immaterial. Also,
that the standard calls the syntactic element involved a "condition" is
immaterial.

It is possible that chess player thinks that a knights move is one step
diagonal followed by an outward one step rook move. Now some rule book
could defined it as a two step rook move followed by a one step rook move
in a perpendicular direction. There will never be any observable
disagreement between the player and the rule book. There is no reason the
player should change his way of thinking.


Best

Kai-Uwe Bux
 
A

Alf P. Steinbach

* Kai-Uwe Bux:
James Kanze wrote:
[snip]
(But if I
understand your argument correctly, you're not arguing for the
conversion, but rather that "conditions" can take many different
types, and not just bool. Which sounds like an oxymoron to me.)

That is confusing the definitions of the standard with how one thinks about
language constructs. The implicit conversion are crafted so that

if ( expr ) { ... }

is for all practical purposes equivalent to

if ( expr != 0 ) { ... }

So, one may think about if-clauses as testing for non-zeroness. That the
standard accomplishes this by implicit conversions is immaterial. Also,
that the standard calls the syntactic element involved a "condition" is
immaterial.

It is possible that chess player thinks that a knights move is one step
diagonal followed by an outward one step rook move. Now some rule book
could defined it as a two step rook move followed by a one step rook move
in a perpendicular direction. There will never be any observable
disagreement between the player and the rule book. There is no reason the
player should change his way of thinking.

I think this is like discussing the general issue of # of angels that can fit on
a dog's snout without causing the dog to sneeze.

But anyways, in a broader perspective it is about adopting consistent coding
conventions, and about deviating from such conventions in certain idiomatic cases.

For full consistency, allowing a later change from raw pointer to smart pointer,
one should ideally write e.g.

if( !isZero( p ) ) { ... }

and not as Andrew likes

if( p ) { ... }

or as James and I like

if( p != 0 ) { ... }

or as some have advocated elsewhere,

if( p != nullPtr )

But in reality the effort of using something like 'isZero' will mostly be
wasted: the pointer's type will probably never be changed. And wasted effort is
generally ungood. So upshot is to do what's natural, what one's accustomed to,
unless there are coding guidelines that force some particular way.


Cheers,

- Alf
 
J

James Kanze

James Kanze wrote:
(But if I
understand your argument correctly, you're not arguing for the
conversion, but rather that "conditions" can take many different
types, and not just bool. Which sounds like an oxymoron to me.)
That is confusing the definitions of the standard with how one
thinks about language constructs. The implicit conversion are
crafted so that
if ( expr ) { ... }
is for all practical purposes equivalent to
if ( expr != 0 ) { ... }

Yes. But that's an implicit conversion (and a lossy one, at
that)---a bit of obfuscation, if you prefer, present mainly for
reasons of backwards compatibility. Or, perhaps, as a technical
means of supporting what Andy seems to be arguing for:
conditions that don't really require booleans. (Sort of like
saying, in English "if the address", rather than "if the address
is present", or "if the address is valid".)
So, one may think about if-clauses as testing for
non-zeroness. That the standard accomplishes this by implicit
conversions is immaterial. Also, that the standard calls the
syntactic element involved a "condition" is immaterial.

And the fact that it uses key words like if and while, who's
meaning in English implies a predicate, is also irrelevant?
That's what I mean when I said it seems like an oxymoron.
Saying that we have an if that tests something that isn't a
predicate seems to me an internal contradiction.

I can sort of understand his point of view (although I still
don't agree) IF we accept the idea of "null", in the data base
sense. This has serious repercussions, however; if we implement
it systematically, all types should be "null-able", so even bool
ends up with three states (true, false and null), and "if
( aBool )" executes the if clause if aBool is true or false (but
not if it is null). I don't think that's really a direction C++
wants to take. (While I can partially see the argument for "if
(pointer)"---a null pointer is a very special, sentinal
value---I can't accept it at all for "if (number)", where number
is a double or an int. There's nothing particularly special
about 0, and for example, open(), under Unix, uses -1 as its
special return value.)

In the end, C++ has taken the route of increasing type safety
(compared to C). Not quite as much as it should, IMHO---I'd
like to see implicit conversions of double to int, for example,
dropped. But the type system is important in C++. And
explicitly providing a bool in a condition is part of that type
system; supporting things like "if (p)" is a crack in that type
system.
 
J

James Kanze

* Kai-Uwe Bux:

[...]
For full consistency, allowing a later change from raw pointer
to smart pointer, one should ideally write e.g.
if( !isZero( p ) ) { ... }
and not as Andrew likes
if( p ) { ... }
or as James and I like

if( p != 0 ) { ... }

Well, I prefer "if ( p != NULL )":). But the choice of 0 or
NULL is another argument---fundamentally, neither are really
satisfactory, for different reasons.

And of course, any smart pointer worth its salt will support
comparison with a null pointer constant. (All of the ones I've
written do.) Or implicit conversion to bool, if you really want
to take that route.
or as some have advocated elsewhere,
if( p != nullPtr )

Except that it will be spelled nullptr in C++0x (and apparently
enough people were dissatisfied with 0 or NULL to do something
about it).
But in reality the effort of using something like 'isZero'
will mostly be wasted: the pointer's type will probably never
be changed. And wasted effort is generally ungood. So upshot
is to do what's natural, what one's accustomed to, unless
there are coding guidelines that force some particular way.

And we're discussing what should be in the coding guidelines:).
 
G

Guest

I thought it has something to do with the fact that with C an invalid
pointer was not necessarily set to 0 on all platforms,

an invalid pointer can be set to anything (that isn't a valid
pointer), but a null pointer will have a specific value for
that implementation (usually all bits zero). Assigning 0 to
a pointer will set it to the value null pointer.

int* p = 0; // p is now set to a null pointer value

In C (and C++) this works

if (p == 0)

*no matter what value the null pointer value has*

Most of the time C (and C++) programmers don't have to
worry thet the null pointer value may not be zero
unless they start breaking into types

int i = 0;
int *p = (int*)i; // this won't work!!

hence the need for a special value.

nope. NULL is just a convenience. And it *must* evaluate to
0 (or (void*)0 in C).
Something that C++ decided not to carry on, and
used 0 for invalid pointers; thus legitimating the usage of implicit
conversion to bool.

C and C++ have (nearly) the same semantics in this area.

// all these are ok in C and C++
int* p = NULL;
p = 0;
if (p)
if (p == 0)
if (p == NULL)

// these work in C but not in C++
int* p = (void*)0;
p = malloc (127);

When C++ was young and stdlib was sometimes lifted from
C the NULL macro sometimes didn't work with C++ hence
C++ programmers used the unadorned 0 as that always works.
NULL should be ok now but is avoided for historical
reasons.

Some have suggested that 0 is a special keyword
that means null pointer...
 
G

gpderetta

I can sort of understand his point of view (although I still
don't agree) IF we accept the idea of "null", in the data base
sense.  

In my point of view there are two uses of pointers:

- pointer-as-iterators, which always go around in pairs. The pointers
point to rages of things and have no business having a null state and
should never be checked for null-ness. A test for emptiness (begin ==
end) is the logical null state.

- pointer as a nullable references. In this case null really is a
special value, exactly as in the database sense. On the other hand you
should never do pointer arithmetic on these kind of pointers: these
are not iterators.

These really are two different things; the fact that both usages are
encoded using pointers is a bit unfortunate, but of course it is due
to historical reasons.
This has serious repercussions, however; if we implement
it systematically, all types should be "null-able", so even bool
ends up with three states (true, false and null), and "if
( aBool )" executes the if clause if aBool is true or false (but
not if it is null).

Well, nothing forces you to implement it systematically. You can
always add an extra null state with the fallible idiom, if necessary
(heck, I've even used boost::eek:ptional<T&> as a nullable reference
parameter, but it is usually an overkill).

The fact is that pointers do come with a builtin out-of-band-really-
can-t-be-used-for-anything-else null state; IMHO making the check
explicit doesn't add much.
I don't think that's really a direction C++
wants to take.  (While I can partially see the argument for "if
(pointer)"---a null pointer is a very special, sentinal
value---I can't accept it at all for "if (number)", where number
is a double or an int.  There's nothing particularly special
about 0, and for example, open(), under Unix, uses -1 as its
special return value.)

for what is worth, while I routinely use the 'if(ptr)' idiom, I
(almost) always write 'if(integral == 0)' explicitly, exactly because
0 is not usually a special value for numbers.
In the end, C++ has taken the route of increasing type safety
(compared to C).  Not quite as much as it should, IMHO---I'd
like to see implicit conversions of double to int, for example,
dropped.  But the type system is important in C++.  And
explicitly providing a bool in a condition is part of that type
system; supporting things like "if (p)" is a crack in that type
system.

the crack is not the 'if(p)' itself, but all implicit conversions to
bool, which lose information. If all bool conversions were explicit
and 'if(p)' were considered an explicit bool conversion context (which
makes sense, as 'if' is obviously asking for a boolean question), it
wouldn't be a problem (in fact, IIRC, this is how the current draft
treats 'explicit operator bool()')
 
J

James Kanze

On 30 Jan, 21:36, Bertrand <[email protected]> wrote:

[Excellent description of the situation elided...]
When C++ was young and stdlib was sometimes lifted from
C the NULL macro sometimes didn't work with C++ hence
C++ programmers used the unadorned 0 as that always works.
NULL should be ok now but is avoided for historical
reasons.

I'm under the impression that the original impetus for using 0
was also the occasional problems with the way NULL was defined.
But today, at least, other motivations exist: NULL can lead to
confusion in cases of function overload or templates:

void f( int ) ;
void f( char* ) ;

f( NULL ) ; // calls f( int ) !!!

People who use a lot of overloaded functions or a lot of
templates tend to prefer 0 to NULL for this reason. People who
overload more reasonably (i.e. who only overload when it doesn't
matter which function is called), and make more limited use of
templates (for whatever reasons) tend to prefer NULL. I'm in
the NULL camp, but I understand the arguments on the other side;
they're not just caught up in an anachronism. (None of those
reasons apply to C, of course, and I don't understand why one
would use 0 instead of NULL in the case of C.)
Some have suggested that 0 is a special keyword
that means null pointer...

Which works in C. According to the standard, there is a
conversion involved. In the case of C, I can't think of any
case where it makes a difference, but in C++, it affects
function overload resolution and template type deduction.

Given that both 0 and NULL have problems in C++, the
standardization committee has added a nullptr keyword, which
resolves to a constant expression of a special type, which isn't
an integer. G++ has implemented this for a long time, of
course, although it's nullptr (spelled __null) is designed to
behave as an int, except that it generates a warning if it
doesn't get immediately converted to a pointer.
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,147
Latest member
CarenSchni
Top