Topic: Why's of C++ -- Part 1


Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/08/24
Raw View
David R Tribble <david@tribble.com> writes:

>Steve Clamage wrote:
>> ...
>> 2. The standard requires NULL to have an integer type. An enum is
>> not an integer type.

>So is an implementation allowed to have:

>    // <cstddef>
>    enum { __null };
>    #define NULL  ((int)__null)

Yes. It's also allowed to have
 #define NULL ((1+1)-(2/2)+(3%3)/(4*4))
but what would be the point?

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/23
Raw View
In article <37BED48E.8BC73558@acm.org>,
  Pete Becker <petebecker@acm.org> wrote:
> James.Kanze@dresdner-bank.com wrote:

> > The resolution of overloading is determined uniquely by the type.
> > Whether something is a null pointer constant or not is
> > irrelevant. In this specific case, 0 is a null pointer constant of
> > type int.  The overload resolution treats it exactly as if it were
> > any other int.

> Yes, sorry about being cranky the other day. I think we're saying the
> same thing, on different levels: overloading is not affected by the
> label "null pointer constant." Being a null pointer constant is an
> unstable quantum mechanical state that disappears as soon as you try
> to look for it.

I like that way of looking at it.  A null pointer constant is a
particular syntactical construct, and has no existance (as such) at
run-time.  The semantics of the construct are to allow the compiler to
make a certain number of compile-time conversions that it couldn't
otherwise.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/08/23
Raw View
In article
<christian.bau-2008991035470001@christian-mac.isltd.insignia.com>,
  christian.bau@isltd.insignia.com (Christian Bau) wrote:
> In article <37BB6DF8.A3F36FA3@acm.org>, Pete Becker
<petebecker@acm.org> wrote:
>
> > James.Kanze@dresdner-bank.com wrote:

> > > Section 18.1: "The macro NULL is an implementation-defined C++
> > > null pointer constant in this International Standard."  No words
> > > about may or may not be, according to context.

> > Then in this case:

> > void f(int);
> > void f(void*);

> > f(NULL) is required to call f(void*)? f(0) is, too? And in order to
> > call f(int) we have to say f((int)0)?

> Here are the C rules, which are (I hope) identical to the C++ rules,
> except for the definition what constitutes a null pointer constant:

Not quite.  C++ makes a difference between initialization and assignment
(not really relevant here, but it does mean that identical wording
doesn't say the same thing), and C++ doesn't have an implicit conversion
from void* to other pointer types.

> A "null pointer constant" is not necessarily a pointer.

In C++, a "null pointer constant" is not allowed to be a pointer.

> Only if you
> use it in an assignment to a pointer, it is replaced by a null pointer
> of the appropriate type. And if you use it in a comparison using == or
> != to compare it to a pointer, it becomes a null pointer of the
> appropriate type. In any other situation, it doesnt matter that an
> expression is a null pointer constant.

And if you pass it to a function declared as taking a pointer type as
argument.  And if you use it as a return value for a function returning
a pointer type.  And perhaps a few other cases which I've forgotten as
well.

In C++, most, if not all, of these cases are covered by the rules of
initialization.

> If C++ were changed to allow both 0 and ((void *) 0) as null pointer
> constants, then f (NULL) would be either f (0) or f ((void *) 0),

The proposal would also have required NULL to be defined as "(void*)0".

> depending on your implementation. It doesn't matter that the argument
> happens to be a null pointer constant, because there is no assignment
> or comparison anywhere near it.

But in C++, there is an initialization.  And in C, null pointer
constants work when being passed as arguments to a declared parameter as
well.

> So depending on your implementation,
> either f (int) or f (void *) will be called, and on your
> implementation this will unambigous - on a different implementation,
> you might get an unambigous call to the other function.

This is irrespective of the current argument, and is a natural result of
function overload resolution.  Currently, depending on the
implementation, either f(int) will be called, or the call will be
ambiguous.  The proposal would mean that f(void*) would be called.

> I think a lot of confusion comes from the fact that a C compiler that
> doesn't implement null pointer constants correctly usually gets away
> with it:

What do you mean by "doesn't implement null pointer constants
correctly."  I've never used a C compiler which didn't implement them
correctly, as required by the C standard.

> If you write in C

>    char* p = (void *) 0;

> then a C compiler should see that (void *) 0 is a null pointer
constant,
> and therefore replace it with a null pointer of type char*. If the
> compiler incorrectly doesnt recognise the null pointer constant, then
it
> will

>    Take the integer value 0.
>    Calculate the implementation-defined result of casting 0 to void*.
>    Automatically cast the void* to char*. /* That doesnt happen in C++
*/

So.  Typically, the representation of a null pointer and the integral
constant 0 (of the same size) will be the same -- the compiler writer
(who is defining the implementation) is allowed to take advantage of
this fact.  At the machine level, there is typically no distinction
anyway: its all just so many bits.

With regards to recognizing the null pointer constant: the compiler must
do this in any case, since

    char* p = 0 ;

is legal, but assigning a non-constant integral expression, or one whose
value isn't 0, isn't.

(It's probably true that most C compilers cover the extension of null
pointer constant to void* by ignoring it, knowing that a conforming
program cannot tell.  And that doing the same in C++ will not work,
because the void*, not being recognized as a null pointer, will not
convert to other pointer types.  Perhaps this is what you are trying to
say.)

> Which is not guaranteed to produce a null pointer, but it does on most
> implementations. In C++, the compiler would have to recognise the null
> pointer constant.

Correct.  But in C and in C++, the compiler must have special code to
recognize the null pointer constant anyway, in order to handle 0.  So
extending it to handle (void*)0 should not pose any problems.  (For what
it's worth, g++ already does this.  If I remember correctly, Fergus told
me that it took only two lines of code for him to implement my proposal
in g++.)

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/23
Raw View
In article <37BD8E33.316D7FEA@tribble.com>,
  David R Tribble <david@tribble.com> wrote:
> James.Kanze@dresdner-bank.com wrote:
> >
> > Pete Becker <petebecker@acm.org> wrote:
> >> NULL itself is a macro whose expansion typically is 0, and 0 is an
> >> int. When used in an appropriate context, NULL is a null pointer
> >> constant. When used in other contexts it is an int. So NULL may or
> >> may not be a null pointer constant, depending on how you use it.
> >
> > Section 18.1: "The macro NULL is an implementation-defined C++ null
> > pointer constant in this International Standard."  No words about
> > may or may not be, according to context.
>
> And yet the following is conforming, portable code:
>
>     int   i =3D NULL;
>     char  c =3D NULL;
>     if (c =3D=3D NULL)
>         std::memset(buf, NULL, sizeof(buf));
>
> NULL is a pointer constant,

NULL is a null pointer constant.  But a null pointer constant is *not* a
pointer, nor a null pointer -- it is only something which will convert
implicitly to a null pointer is a given context.

> but the way ISO C++ defines it (or more
> precisely, the way it must be actually be implemented), it is also
> an integer constant.  It is both, and semantic context determines
> whether it is treated as having an integer or a pointer type.

Strictly speaking, I'd prefer to say that it is never treated as having
pointer type.  It is a special syntax which allows an integral type to
convert implicitly to pointer type.  But a conversion is *always*
involved; in C, this makes no difference, but in C++, it plays a role in
overload resolution.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient=E9e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jeff Rife <jrifeSPAM@BEnabsGONE.net>
Date: 1999/08/23
Raw View
James.Kanze@dresdner-bank.com (James.Kanze@dresdner-bank.com) wrote:

> The order of presentation is important.  The standard defines null
> pointer constant without the slightest reference to NULL.  It then
> defines NULL, requiring it to be something which expands to a null
> pointer constant.

I understand that, but the language of the standard forces NULL to
have a very limited choice for definitions, so most of my argument holds.

In addition, I think this part of the standard is what we are all
complaining about, because *there is nothing magical about the NULL
macro*.  It's just a C-style preprocessor macro...nothing more.

> The only thing a compiler can do is consider any constant integral
> expression which evaluates to 0 to be a null pointer constant.  Which,
> of course, doesn't change its type in any way, nor change the fact that
> it is an *integral* constant expression, and not a pointer.

Agreed.  I think we said the same thing, only in slightly different
ways.  The point being, the compiler can't know what we *meant*, but
only what it sees...and all it sees is an integer.

> No. "integer constant 0 == null pointer constant".  The whole point of
> my posting is that despite the names, a null pointer constant is *not* a
> null pointer.  It is an integral constant expression.  And it can be
> converted to a null pointer, if the context requires.  But it only
> becomes a null pointer after the conversion.

...and, the code is only executable after it is compiles.  Your point
being?

What I mean is that the compiler does a *lot* of conversions/translations/
interpretations on the way to producing finished code.  It is the whole
of this work that makes a "standard C++ compiler".  (Now, I know that
there are certain phases of translation required by the compilier, but I
fail to see how an implementaion that performs all the required tasks
would be considered to be "not conforming" just because it doesn't have
an explicit pass for every required translation phase.)

Thus, in source code, an integer constant 0 in a pointer context (which
is really the problem here...what *is* a pointer context?) is a null
pointer constant, which, in compiled code is a null pointer.  Thus
an integer constant 0 is the only way we can represent a null pointer
in source code, so you might as well call it that.

--
Jeff Rife                   | "You fell victim to one of the classic blunders,
19445 Saint Johnsbury Lane  |  the most famous of which is 'Never get involved
Germantown, MD  20876-1610  |  in a land war in Asia', but only slightly less
Home: 301-916-8131          |  famous is this: 'Never go in against a Sicilian,
Work: 301-770-5800 Ext 5335 |  when death is on the line!'"
                            |              -- Vizzini, The Princess Bride
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1999/08/23
Raw View
In article <37BB6DF8.A3F36FA3@acm.org>, Pete Becker <petebecker@acm.org> wrote:

> James.Kanze@dresdner-bank.com wrote:
> >
> > Section 18.1: "The macro NULL is an implementation-defined C++ null
> > pointer constant in this International Standard."  No words about may or
> > may not be, according to context.
> >
>
> Then in this case:
>
> void f(int);
> void f(void*);
>
> f(NULL) is required to call f(void*)? f(0) is, too? And in order to call
> f(int) we have to say f((int)0)?

Here are the C rules, which are (I hope) identical to the C++ rules,
except for the definition what constitutes a null pointer constant:

A "null pointer constant" is not necessarily a pointer. Only if you use it
in an assignment to a pointer, it is replaced by a null pointer of the
appropriate type. And if you use it in a comparison using == or != to
compare it to a pointer, it becomes a null pointer of the appropriate
type. In any other situation, it doesnt matter that an expression is a
null pointer constant.

If C++ were changed to allow both 0 and ((void *) 0) as null pointer
constants, then f (NULL) would be either f (0) or f ((void *) 0),
depending on your implementation. It doesn't matter that the argument
happens to be a null pointer constant, because there is no assignment or
comparison anywhere near it. So depending on your implementation, either f
(int) or f (void *) will be called, and on your implementation this will
unambigous - on a different implementation, you might get an unambigous
call to the other function.

I think a lot of confusion comes from the fact that a C compiler that
doesn't implement null pointer constants correctly usually gets away with
it: If you write in C

   char* p = (void *) 0;

then a C compiler should see that (void *) 0 is a null pointer constant,
and therefore replace it with a null pointer of type char*. If the
compiler incorrectly doesnt recognise the null pointer constant, then it
will

   Take the integer value 0.
   Calculate the implementation-defined result of casting 0 to void*.
   Automatically cast the void* to char*. /* That doesnt happen in C++ */

Which is not guaranteed to produce a null pointer, but it does on most
implementations. In C++, the compiler would have to recognise the null
pointer constant.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/23
Raw View
In article <MPG.1226369ffe1958bb9896bf@news.nabs.net>,
  Jeff Rife <jrifeSPAM@BEnabsGONE.net> wrote:
> Pete Becker (petebecker@acm.org) wrote:
>
> > James.Kanze@dresdner-bank.com wrote:

> > > Section 4.10: "A null pointer constant is an integral constant
> > > expression rvalue of integer type that evaluates to zero."  No
> > > hint about "can be".

> > > Section 18.1: "The macro NULL is an implementation-defined C++
> > > null pointer constant in this International Standard."  No words
> > > about may or may not be, according to context.

> Actually, using macro substitution in the text of the standard, we
> would arrive at:

> The macro NULL is an implementation-defined integral constant
> expression rvalue of integer type that evaluates to zero in this
> International Standard.

> [note: this *does not* appear in the Standard, and I'm not saying it
> does, I'm just using it to help clarify things]

> This is *all* the standard says about NULL:

> 1. It is a macro
> 2. It is implementation-defined
> 3. It is a integer constant expression
> 4. It evaluates to 0

> > Then in this case:
> >
> > void f(int);
> > void f(void*);
> >
> > f(NULL) is required to call f(void*)? f(0) is, too? And in order to
call
> > f(int) we have to say f((int)0)?
>
> No, and I don't know how you read James' post to get this.
>
> But, the problem is that the standard says that some macro named NULL
> must be translated by the pre-processing phase into an integer
> constant that evaluates to 0.  I don't see how this can mean anything
> other than the compiler seeing something that == 0.

> It also says that this NULL (not 0, but there is *no* guarantee that a
> compiler gets to see the "NULL" anywhere) macro is a null pointer
> constant.

Not really.  What it says is that 0 is a null pointer constant.  As you
say, NULL doesn't exist after macro expansion; whether the 0 is a result
of the expansion of NULL or not is irrelevant.

The order of presentation is important.  The standard defines null
pointer constant without the slightest reference to NULL.  It then
defines NULL, requiring it to be something which expands to a null
pointer constant.

> The *only* thing a compiler can do is assume that any constant integer
> expression that evaluates to 0 *might* be an attempt by us sorry
> humans to try and use a null pointer.

The only thing a compiler can do is consider any constant integral
expression which evaluates to 0 to be a null pointer constant.  Which,
of course, doesn't change its type in any way, nor change the fact that
it is an *integral* constant expression, and not a pointer.

> It must do that by context.

> Because of that, your example should elicit a diagnostic, because *the
> compiler cannot know from this context*, so it should tell us that.

> From another point of view, we have:

> integer constant 0 ==  null pointer

No. "integer constant 0 == null pointer constant".  The whole point of
my posting is that despite the names, a null pointer constant is *not* a
null pointer.  It is an integral constant expression.  And it can be
converted to a null pointer, if the context requires.  But it only
becomes a null pointer after the conversion.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david@tribble.com>
Date: 1999/08/23
Raw View
Steve Clamage wrote:
>
> "Ken Hagan" <K.Hagan@thermoteknix.co.uk> writes:
>
> >Would
> >   #undef NULL
> >   enum {NULL};
> >be too awful to contemplate?
>
> 1. Redefining a standard macro in your code is never a good idea.
> You don't know what assumptions in the implementation might break.
>
> 2. The standard requires NULL to have an integer type. An enum is
> not an integer type.

So is an implementation allowed to have:

    // <cstddef>
    enum { __null };
    #define NULL  ((int)__null)

-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david@tribble.com>
Date: 1999/08/23
Raw View
James.Kanze@dresdner-bank.com wrote:
>
> Pete Becker <petebecker@acm.org> wrote:
>> NULL itself is a macro whose expansion typically is 0, and 0 is an
>> int. When used in an appropriate context, NULL is a null pointer
>> constant. When used in other contexts it is an int. So NULL may or
>> may not be a null pointer constant, depending on how you use it.
>
> Section 18.1: "The macro NULL is an implementation-defined C++ null
> pointer constant in this International Standard."  No words about
> may or may not be, according to context.

And yet the following is conforming, portable code:

    int   i = NULL;
    char  c = NULL;
    if (c == NULL)
        std::memset(buf, NULL, sizeof(buf));

NULL is a pointer constant, but the way ISO C++ defines it (or more
precisely, the way it must be actually be implemented), it is also
an integer constant.  It is both, and semantic context determines
whether it is treated as having an integer or a pointer type.

-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Pete Becker <petebecker@acm.org>
Date: 1999/08/23
Raw View
James.Kanze@dresdner-bank.com wrote:
>
> The resolution of overloading is determined uniquely by the type.
> Whether something is a null pointer constant or not is irrelevant.  In
> this specific case, 0 is a null pointer constant of type int.  The
> overload resolution treats it exactly as if it were any other int.
>

Yes, sorry about being cranky the other day. I think we're saying the
same thing, on different levels: overloading is not affected by the
label "null pointer constant." Being a null pointer constant is an
unstable quantum mechanical state that disappears as soon as you try to
look for it.

--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/20
Raw View
In article <37BB6DF8.A3F36FA3@acm.org>,
  Pete Becker <petebecker@acm.org> wrote:
>
> James.Kanze@dresdner-bank.com wrote:
> >
> > In article <37B97A29.90004152@acm.org>,
> >   Pete Becker <petebecker@acm.org> wrote:
> > > James.Kanze@dresdner-bank.com wrote:
> > > >
> > > > In article <37B1D71F.5DD43065@acm.org>,
> > > >   Pete Becker <petebecker@acm.org> wrote:
> > > >
> > > > > In C, NULL is a macro that
> > > > > expands to a null pointer constant. In C++ it is not.
> >
> > > > No.  Both in C and C++, NULL is a macro that expands to a null
> > > > pointer constant.  The problem is that there is no type "null
> > > > pointer constant"; a null pointer constant has an integral type
(or
> > > > in C, void*).

> > > > Note that this leads to the somewhat surprising conclusion (that
> > > > you sort of point out in the part I cut) that a null pointer
> > > > constant is *not* a null pointer.  (On the other hand, a null
> > > > pointer constant will convert implicitly to a null pointer of a
> > > > specific type in all contexts where the compiler knows that a
> > > > pointer is expected.)

> > > There are words in the standard that say that 0 can be a null
> > > pointer constant, depending on context.

> > Section 4.10: "A null pointer constant is an integral constant
> > expression rvalue of integer type that evaluates to zero."  No hint
> > about "can be".

> > > NULL itself is a macro whose expansion typically is 0, and 0 is an
> > > int. When used in an appropriate context, NULL is a null pointer
> > > constant. When used in other contexts it is an int. So NULL may or
> > > may not be a null pointer constant, depending on how you use it.

> > Section 18.1: "The macro NULL is an implementation-defined C++ null
> > pointer constant in this International Standard."  No words about
> > may or may not be, according to context.

> Then in this case:

> void f(int);
> void f(void*);

> f(NULL) is required to call f(void*)? f(0) is, too? And in order to
> call f(int) we have to say f((int)0)?

No.  Reread my original posting.  According to the standard, 0 is a null
pointer constant.  But according to the standard, a null pointer
constant is *not* a null pointer, and cannot have a pointer type.  A
null pointer constant is a compile time construct; a null pointer is
purely a run-time value.

The resolution of overloading is determined uniquely by the type.
Whether something is a null pointer constant or not is irrelevant.  In
this specific case, 0 is a null pointer constant of type int.  The
overload resolution treats it exactly as if it were any other int.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/08/18
Raw View
In article <37B97A29.90004152@acm.org>,
  Pete Becker <petebecker@acm.org> wrote:
> James.Kanze@dresdner-bank.com wrote:
> >
> > In article <37B1D71F.5DD43065@acm.org>,
> >   Pete Becker <petebecker@acm.org> wrote:
> >
> > > In C, NULL is a macro that
> > > expands to a null pointer constant. In C++ it is not.

> > No.  Both in C and C++, NULL is a macro that expands to a null
> > pointer constant.  The problem is that there is no type "null
> > pointer constant"; a null pointer constant has an integral type (or
> > in C, void*).

> > Note that this leads to the somewhat surprising conclusion (that you
> > sort of point out in the part I cut) that a null pointer constant is
> > *not* a null pointer.  (On the other hand, a null pointer constant
> > will convert implicitly to a null pointer of a specific type in all
> > contexts where the compiler knows that a pointer is expected.)

> There are words in the standard that say that 0 can be a null pointer
> constant, depending on context.

Section 4.10: "A null pointer constant is an integral constant
expression rvalue of integer type that evaluates to zero."  No hint
about "can be".

> NULL itself is a macro whose expansion
> typically is 0, and 0 is an int. When used in an appropriate context,
> NULL is a null pointer constant. When used in other contexts it is an
> int. So NULL may or may not be a null pointer constant, depending on
> how you use it.

Section 18.1: "The macro NULL is an implementation-defined C++ null
pointer constant in this International Standard."  No words about may or
may not be, according to context.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/08/19
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

>BTW, if an _implementor_ did

>enum { __null };
>#define NULL __null;

>would that be conforming?

No. The standard requires that NULL expand to an expression of integer
type (18.1 and 4.10).  Enums are not integer types (3.9.1/7
and 3.9.2/1).

I can't offhand think of a program that could detect the difference.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/08/19
Raw View
"Ken Hagan" <K.Hagan@thermoteknix.co.uk> writes:

>Would
>   #undef NULL
>   enum {NULL};
>be too awful to contemplate?

1. Redefining a standard macro in your code is never a good idea.
You don't know what assumptions in the implementation might break.

2. The standard requires NULL to have an integer type. An enum is
not an integer type.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Pete Becker <petebecker@acm.org>
Date: 1999/08/19
Raw View
James.Kanze@dresdner-bank.com wrote:
>
> In article <37B97A29.90004152@acm.org>,
>   Pete Becker <petebecker@acm.org> wrote:
> > James.Kanze@dresdner-bank.com wrote:
> > >
> > > In article <37B1D71F.5DD43065@acm.org>,
> > >   Pete Becker <petebecker@acm.org> wrote:
> > >
> > > > In C, NULL is a macro that
> > > > expands to a null pointer constant. In C++ it is not.
>
> > > No.  Both in C and C++, NULL is a macro that expands to a null
> > > pointer constant.  The problem is that there is no type "null
> > > pointer constant"; a null pointer constant has an integral type (or
> > > in C, void*).
>
> > > Note that this leads to the somewhat surprising conclusion (that you
> > > sort of point out in the part I cut) that a null pointer constant is
> > > *not* a null pointer.  (On the other hand, a null pointer constant
> > > will convert implicitly to a null pointer of a specific type in all
> > > contexts where the compiler knows that a pointer is expected.)
>
> > There are words in the standard that say that 0 can be a null pointer
> > constant, depending on context.
>
> Section 4.10: "A null pointer constant is an integral constant
> expression rvalue of integer type that evaluates to zero."  No hint
> about "can be".
>
> > NULL itself is a macro whose expansion
> > typically is 0, and 0 is an int. When used in an appropriate context,
> > NULL is a null pointer constant. When used in other contexts it is an
> > int. So NULL may or may not be a null pointer constant, depending on
> > how you use it.
>
> Section 18.1: "The macro NULL is an implementation-defined C++ null
> pointer constant in this International Standard."  No words about may or
> may not be, according to context.
>

Then in this case:

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

f(NULL) is required to call f(void*)? f(0) is, too? And in order to call
f(int) we have to say f((int)0)?

--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/08/19
Raw View
In article <37BAD2D4.6B0B164A@physik.tu-muenchen.de>,
  Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:

> BTW, if an _implementor_ did

> enum { __null };
> #define NULL __null;
>
> would that be conforming?

In C, yes (I think).  In C++, no.  The standard requires that NULL be
defined as a null pointer constant, and defines a null pointer constant
as being a constant integral expression evaluating to null.  An enum
constant is not an integral expression.

Could a conforming program tell.  Regretfully yes:

    #include <cstddef>
    #include <iostream>

    static int instantiatedTypes = 0 ;

    template< class T >
    void
    f( T )
    {
        static bool     firstTime = true ;
        if ( firstTime ) {
            ++ instantiatedTypes ;
            firstTime = false ;
        }
    }

    int
    main()
    {
        f( (char)0 ) ;
        f( (unsigned char)0 ) ;
        f( (signed char)0 ) ;
        f( (short)0 ) ;
        f( (unsigned short)0 ) ;
        f( (int)0 ) ;
        f( (unsigned int)0 ) ;
        f( (long)0 ) ;
        f( (unsigned long)0 ) ;
        f( (wchar_t)0 ) ;
        f( NULL ) ;
        std::cout << instantiatedTypes << '\n' ;
        return 0 ;
    }

This program is guaranteed to output 10 in a conforming implementation.
(Note that similar tricks can be used to ensure that size_t or ptrdiff_t
are also legal integral types, and not long long or __int64.)

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/19
Raw View
In article <7peu71$go1$1@engnews1.eng.sun.com>, Steve Clamage
<clamage@eng.sun.com> writes
>No. The standard requires that NULL expand to an expression of integer
>type (18.1 and 4.10).  Enums are not integer types (3.9.1/7
>and 3.9.2/1).

Is that documented as a difference with C (I mean in the very specific
case of treating an enumeration constant with value 0 as the null
pointer constant)

>
>I can't offhand think of a program that could detect the difference.
>

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jeff Rife <jrifeSPAM@BEnabsGONE.net>
Date: 1999/08/19
Raw View
Pete Becker (petebecker@acm.org) wrote:

> James.Kanze@dresdner-bank.com wrote:
> >
> > Section 4.10: "A null pointer constant is an integral constant
> > expression rvalue of integer type that evaluates to zero."  No hint
> > about "can be".
> >
> > Section 18.1: "The macro NULL is an implementation-defined C++ null
> > pointer constant in this International Standard."  No words about may or
> > may not be, according to context.
>

Actually, using macro substitution in the text of the standard, we would
arrive at:

The macro NULL is an implementation-defined integral constant
expression rvalue of integer type that evaluates to zero in this
International Standard.

[note: this *does not* appear in the Standard, and I'm not saying it does,
       I'm just using it to help clarify things]

This is *all* the standard says about NULL:

1. It is a macro
2. It is implementation-defined
3. It is a integer constant expression
4. It evaluates to 0

> Then in this case:
>
> void f(int);
> void f(void*);
>
> f(NULL) is required to call f(void*)? f(0) is, too? And in order to call
> f(int) we have to say f((int)0)?

No, and I don't know how you read James' post to get this.

But, the problem is that the standard says that some macro named NULL
must be translated by the pre-processing phase into an integer
constant that evaluates to 0.  I don't see how this can mean anything
other than the compiler seeing something that == 0.

It also says that this NULL (not 0, but there is *no* guarantee that a
compiler gets to see the "NULL" anywhere) macro is a null pointer
constant.  The *only* thing a compiler can do is assume that any constant
integer expression that evaluates to 0 *might* be an attempt by us
sorry humans to try and use a null pointer.  It must do that by context.

Because of that, your example should elicit a diagnostic, because *the
compiler cannot know from this context*, so it should tell us that.

>From another point of view, we have:

integer constant 0 ==  null pointer
  for some integer ==> pointer

Wasn't the "pointers are not integers" rant one of the big C
standardization issues, and wasn't it carried over (and made even more
strict in the process) into C++?  So, why do we still face it?

--
Jeff Rife                   |
19445 Saint Johnsbury Lane  | http://www.nabs.net/Cartoons/Dilbert/TechSupport.gif
Germantown, MD  20876-1610  |
Home: 301-916-8131          |
Work: 301-770-5800 Ext 5335 |
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Ken Hagan" <K.Hagan@thermoteknix.co.uk>
Date: 1999/08/18
Raw View
James.Kanze@dresdner-bank.com wrote in message
<7pbp6u$vc7$1@nnrp1.deja.com>...
>
>In article <37B92EEE.46BED44@physik.tu-muenchen.de>,
>  Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>
>> enum { null };
>>
>> this ensures that the compiler will complain about an ambiguity
>> in _every_ case where an overload between an integral type and
>> a pointer type exists.
>
>It also means that everyone trying to read your code will have to learn
>your special convention.  (If you haven't commented the enum, they'll
>even have to think about it for a while before realizing that it is a
>null pointer constant.)

Would
   #undef NULL
   enum {NULL};
be too awful to contemplate?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/18
Raw View
James.Kanze@dresdner-bank.com wrote:
>
> In article <37B92EEE.46BED44@physik.tu-muenchen.de>,
>   Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>
> > If you don't like that type, it's IMHO still better to do
> > something like
> >
> > enum { null };
> >
> > and using that as null pointer, because this ensures that the
> > compiler will complain about an ambiguity in _every_ case
> > where an overload between an integral type and a pointer type
> > exists.
>
> It also means that everyone trying to read your code will have to learn
> your special convention.  (If you haven't commented the enum, they'll
> even have to think about it for a while before realizing that it is a
> null pointer constant.)

But it's a convention easy to learn - and anyone reading my code
will probably have to learn some conventions anyway (naming
conventions, f.ex.). I even suspect that 99%+ of the usages
would be immediatly obvious.

>
> In general: 0 and NULL are supported by the standard and extensive
> existing practice.  Using anything else will make your code harder to
> read.  (Until, of course, that something else becomes part of the
> standard.)

BTW, if an _implementor_ did

enum { __null };
#define NULL __null;

would that be conforming?


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/17
Raw View
Marc Girod wrote:
>
> >>>>> "CE" == Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
> CE> If your compiler is good (i.e. near to the standard), the
> CE> following gives you a null pointer which behaves as wanted:
>
> Furthermore, if you add now:
>
> class A {};
> void foo(A*) { std::cout << "A*" << std::endl; }
>
> you get something like:
>
> Error 225: "foo.C", line 20 # Ambiguous overloaded function call; more than
>     one acceptable function found. Two such functions that matched were "void
>     foo(A *)" ["foo.C", line 19] and "void foo(void *)" ["foo.C", line 17].
>     int main() { foo(null); }
>                  ^^^
>
> which is fine, so that you can disambiguate with:
>
> int main() { foo((A*)null); }
>
> Er... why is this better than "foo((A*) 0)"?

Because before adding the explicit (A*), the original might have
called (erroneously) a foo(int), instead of issuing a compiler
error.
If you don't like that type, it's IMHO still better to do
something like

enum { null };

and using that as null pointer, because this ensures that the
compiler will complain about an ambiguity in _every_ case
where an overload between an integral type and a pointer type
exists.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/17
Raw View
In article <p6qyafiu44j.fsf@informatik.hu-berlin.de>,
  Martin von Loewis <loewis@informatik.hu-berlin.de> wrote:
>
> "Greg Brewer" <nospam.gregb@hal-pc.org> writes:
>
> > Anyone care to comment why the current state is preferable?
>
> That's for C compatibility. In C, people traditionally write
>
> char *tmp = NULL;
> ...
> tmp = (char*)malloc(some_size);
> if (tmp == NULL){
>   // allocation failed
> }

In C, people traditionally write:

    tmp = malloc( some_size ) ;

without the cast.  In fact, the cast is traditionally considered *bad*
practice in such cases -- if you forget to include <stdlib.h>, malloc
will be implicitely declared as returning an int.  With the cast, the
int is cast to a pointer, no problem; without the cast, the code is an
error.

> It was a requirement that such code remains valid. I don't know the
> historic order for introducing '0' as a (preferred) alternative;
> surely one reason was that NULL was defined as many different things
> on different systems.

The historical reason is simple: thanks to operator new, C++ didn't need
the hole in the type system which allowed malloc to be used without the
cast, and so unlike C, void* does *not* convert implicitly to any other
pointer type.  The result is that tmp == NULL is illegal in C++ if NULL
is defined as ((void*)0).

In fact, of course, even in ANSI C, ((void*)0) is a 'null pointer
constant', a special beast which converts to any pointer type regardless
of its formal type.

> Also, note that the alternatives aren't that great, either:

> a) Introduce a null pointer literal (null, nil, None have all been
>    used in various languages). With that, you don't get undesirable
>    overloading with int anymore; it still is ambiguous when
>    overloading on different pointer types. Also, you get a number of
>    new problems:

>    - what is the type of null? Specifically, is
>      typeid(null)==typeid((char*)null)
>    - What type should be used in template argument deduction:
>      template<class T>void foo(T){}
>      foo(null);

You get new problems in the language definition, which have to be
solved.  I don't remember the discussions anymore (and they were long
before DejaNews), but I do remember that at the time, there were
definite advantages with this solution.

> b) Introduce one null pointer literal per type, e.g. ostream::null,
>    int::null, ... This is actually what we have now, you only have to
>    write (int*)0 instead - and it is possible to omit the cast in most
>    cases.

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/17
Raw View
In article <37B1D71F.5DD43065@acm.org>,
  Pete Becker <petebecker@acm.org> wrote:

> In C, NULL is a macro that
> expands to a null pointer constant. In C++ it is not.

No.  Both in C and C++, NULL is a macro that expands to a null pointer
constant.  The problem is that there is no type "null pointer constant";
a null pointer constant has an integral type (or in C, void*).

Note that this leads to the somewhat surprising conclusion (that you
sort of point out in the part I cut) that a null pointer constant is
*not* a null pointer.  (On the other hand, a null pointer constant will
convert implicitly to a null pointer of a specific type in all contexts
where the compiler knows that a pointer is expected.)

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient=E9e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/08/17
Raw View
In article <37B92EEE.46BED44@physik.tu-muenchen.de>,
  Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:

> If you don't like that type, it's IMHO still better to do
> something like
>
> enum { null };
>
> and using that as null pointer, because this ensures that the
> compiler will complain about an ambiguity in _every_ case
> where an overload between an integral type and a pointer type
> exists.

It also means that everyone trying to read your code will have to learn
your special convention.  (If you haven't commented the enum, they'll
even have to think about it for a while before realizing that it is a
null pointer constant.)

In general: 0 and NULL are supported by the standard and extensive
existing practice.  Using anything else will make your code harder to
read.  (Until, of course, that something else becomes part of the
standard.)

--
James Kanze                   mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Pete Becker <petebecker@acm.org>
Date: 1999/08/17
Raw View
James.Kanze@dresdner-bank.com wrote:
>
> In article <37B1D71F.5DD43065@acm.org>,
>   Pete Becker <petebecker@acm.org> wrote:
>
> > In C, NULL is a macro that
> > expands to a null pointer constant. In C++ it is not.
>
> No.  Both in C and C++, NULL is a macro that expands to a null pointer
> constant.  The problem is that there is no type "null pointer constant";
> a null pointer constant has an integral type (or in C, void*).
>
> Note that this leads to the somewhat surprising conclusion (that you
> sort of point out in the part I cut) that a null pointer constant is
> *not* a null pointer.  (On the other hand, a null pointer constant will
> convert implicitly to a null pointer of a specific type in all contexts
> where the compiler knows that a pointer is expected.)

There are words in the standard that say that 0 can be a null pointer
constant, depending on context. NULL itself is a macro whose expansion
typically is 0, and 0 is an int. When used in an appropriate context,
NULL is a null pointer constant. When used in other contexts it is an
int. So NULL may or may not be a null pointer constant, depending on how
you use it.

--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david@tribble.com>
Date: 1999/08/13
Raw View
Greg Brewer wrote:
>
> I do understand that the problem is that a null pointer
> is just a 0 and NULL is simply a #define value for 0.
> ...   It just occurs to me that the problem could be
> solved if a universal null value (eg unull) where defined in the
> same way true and false are now defined.

Welcome to the club.  You might search the news:comp.std.c++ archives
to see how much this issue has been discussed over the last couple
of years.
(See my own proposal at http://david.tribble.com/text/c9xnull.txt,
for example.)

Christopher Eltschka (and probably others) has suggested template
code that implements a workable 'null' constant.  You can use it
today if your compiler handles member templates.

But forget about deprecating the use of 0 as a null pointer; far
too many people do this.

-- David R. Tribble, david@tribble.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Marc Girod <girod@stybba.ntc.nokia.com>
Date: 1999/08/13
Raw View
>>>>> "CE" == Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

CE> If your compiler is good (i.e. near to the standard), the
CE> following gives you a null pointer which behaves as wanted:

Furthermore, if you add now:

class A {};
void foo(A*) { std::cout << "A*" << std::endl; }

you get something like:

Error 225: "foo.C", line 20 # Ambiguous overloaded function call; more than
    one acceptable function found. Two such functions that matched were "void
    foo(A *)" ["foo.C", line 19] and "void foo(void *)" ["foo.C", line 17].
    int main() { foo(null); }
                 ^^^

which is fine, so that you can disambiguate with:

int main() { foo((A*)null); }

Er... why is this better than "foo((A*) 0)"?

--
Marc Girod                Hiomo 5/1          Voice:  +358-9-511 23746
Nokia Telecommunications  P.O. Box 320       Mobile: +358-40-569 7954
NWS/NMS/NMS for Data      00045 NOKIA Group  Fax:    +358-9-511 23580
                          Finland            girod@shire.ntc.nokia.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/11
Raw View
There are a number of issues I have had with C and C++ over the years and
frequently wonder why is it this way.  I thought I might post a few of them
over time and see if some answers don't appear.

The first of the problems is what I term the zero problem.  When I write an
overloaded function or template that can accept either a pointer or an
integer value, the operation works fine unless the value I am sending it is
either NULL or 0.  With those two values, the compiler issues an error about
an ambiguous call.  I do understand that the problem is that a null pointer
is just a 0 and NULL is simply a #define value for 0.

I am aware that it is possible to clear up the ambiguity by forcing a type
(eg (char *)NULL or (int)0).  Moreover, I understand and agree that
automatically promoting pointers up is a bad idea and that a void point
should be now exception.  I just occurs to me that the problem could be
solved if a universal null value (eg unull) where defined in the same way
true and false are now defined.  This universal null would be an untyped
pointer that could be promoted to any type of pointer and 0 could only be an
integer.  By changing the define for NULL to this universal pointer, the
only code that would be broken would be that code that makes use of literal
0 instead of NULL.

Anyone care to comment why the current state is preferable?

Greg Brewer
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1999/08/11
Raw View
"Greg Brewer" <nospam.gregb@hal-pc.org> writes:

> Anyone care to comment why the current state is preferable?

That's for C compatibility. In C, people traditionally write

char *tmp = NULL;
...
tmp = (char*)malloc(some_size);
if (tmp == NULL){
  // allocation failed
}

It was a requirement that such code remains valid. I don't know the
historic order for introducing '0' as a (preferred) alternative;
surely one reason was that NULL was defined as many different things
on different systems.

Also, note that the alternatives aren't that great, either:

a) Introduce a null pointer literal (null, nil, None have all been
   used in various languages). With that, you don't get undesirable
   overloading with int anymore; it still is ambiguous when
   overloading on different pointer types. Also, you get a number of
   new problems:

   - what is the type of null? Specifically, is
     typeid(null)==typeid((char*)null)
   - What type should be used in template argument deduction:
     template<class T>void foo(T){}
     foo(null);

b) Introduce one null pointer literal per type, e.g. ostream::null,
   int::null, ... This is actually what we have now, you only have to
   write (int*)0 instead - and it is possible to omit the cast in most
   cases.

Regards,
Martin


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/11
Raw View
In article <7opqvm$vpa$1@news.hal-pc.org>, Greg Brewer
<nospam.gregb@hal-pc.org> writes
>By changing the define for NULL to this universal pointer, the
>only code that would be broken would be that code that makes use of literal
>0 instead of NULL.

IOWs, most code as there has been long standing advice from eminent C++
gurus to simply use 0 and forgo the problems of NULL being
inconveniently defined (remember that for many years we were likely to
be using plain C header files)



Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1999/08/11
Raw View
In article <7opqvm$vpa$1@news.hal-pc.org>,
Greg Brewer <nospam.gregb@hal-pc.org> wrote:
>The first of the problems is what I term the zero problem.  When I write an
>overloaded function or template that can accept either a pointer or an
>integer value, the operation works fine unless the value I am sending it is
>either NULL or 0.  With those two values, the compiler issues an error about
>an ambiguous call.  I do understand that the problem is that a null pointer
>is just a 0 and NULL is simply a #define value for 0.
....
>Anyone care to comment why the current state is preferable?

For compatibility with C.  This issue is apparently not considered enough
of a problem to warrant doing it differently than C does.

P.S. It would be nice if you would put more context in your Subject line.
Then I wouldn't have had to quote the above paragraph.  Also, when scanning
the newsgroup I'd know which messages are which, rather than having to
remember your part numbers.

--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Pete Becker <petebecker@acm.org>
Date: 1999/08/11
Raw View
Greg Brewer wrote:
>
> There are a number of issues I have had with C and C++ over the years and
> frequently wonder why is it this way.  I thought I might post a few of them
> over time and see if some answers don't appear.
>
> The first of the problems is what I term the zero problem.  When I write an
> overloaded function or template that can accept either a pointer or an
> integer value, the operation works fine unless the value I am sending it is
> either NULL or 0.  With those two values, the compiler issues an error about
> an ambiguous call.
>

You need a new compiler. 0 is of type int, and there is no ambiguity
when you use it as an argument to an overloaded function that has a
version taking an int and a version taking a pointer.

> I do understand that the problem is that a null pointer
> is just a 0 and NULL is simply a #define value for 0.

A null pointer is not "just a 0." It is _a pointer_ with a value that is
distinguishable from all valid pointer values. 0 is not a pointer, it is
an int. In source code the int value 0 can be converted to a null
pointer in contexts that call for a pointer.

One common source of surprise is calling an overloaded function, as you
describe, with an argument of NULL. In C, NULL is a macro that expands
to a null pointer constant. In C++ it is not.

--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/12
Raw View
Greg Brewer wrote:
>
> There are a number of issues I have had with C and C++ over the years and
> frequently wonder why is it this way.  I thought I might post a few of them
> over time and see if some answers don't appear.
>
> The first of the problems is what I term the zero problem.  When I write an
> overloaded function or template that can accept either a pointer or an
> integer value, the operation works fine unless the value I am sending it is
> either NULL or 0.  With those two values, the compiler issues an error about
> an ambiguous call.  I do understand that the problem is that a null pointer
> is just a 0 and NULL is simply a #define value for 0.

If your compiler doesn't compile the following program (or
if the program doesn't print "int"), it is AFAIK broken:

#include <iostream>

void foo(int) { std::cout << "int" << std::endl; }
void foo(void*) { std::cout << "void*" << std::endl; }
int main() { foo(0); }

However, with NULL, it's another case. NULL can be defined to 0,
in which case foo(NULL) calls foo(int). Or NULL can be defined
to 0L, in which case the call is ambiguous. In no case is
f(void*) preferred, though.

>
> I am aware that it is possible to clear up the ambiguity by forcing a type
> (eg (char *)NULL or (int)0).  Moreover, I understand and agree that
> automatically promoting pointers up is a bad idea and that a void point
> should be now exception.  I just occurs to me that the problem could be
> solved if a universal null value (eg unull) where defined in the same way
> true and false are now defined.  This universal null would be an untyped
> pointer that could be promoted to any type of pointer and 0 could only be an
> integer.  By changing the define for NULL to this universal pointer, the
> only code that would be broken would be that code that makes use of literal
> 0 instead of NULL.

If your compiler is good (i.e. near to the standard), the
following gives you a null pointer which behaves as wanted:

class null
{
public:
  template<class T> operator T*() const { return 0; }
  static null get() { return null(); }
private:
  null() {} // needed by get
  null(null const&); // not implemented
};

#define null (null::get())

Now you can use null instead of NULL and always get the correct
overload:

void foo(int) { std::cout << "int" << std::endl; }
void foo(void*) { std::cout << "void*" << std::endl; }
int main() { foo(null); }

now prints "void*".
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]