[comp.lang.c++] Default type of "0"

sdm@cs.brown.edu (Scott Meyers) (05/06/91)

What is the type of the constant "0", independent of any context?  If there
is such a default type, call it T.  Then are there any conversions in any
of the following?

    int i    = 0;  // conversion from T to int?
    int *ip  = 0;  // conversion from T to int*?
    double d = 0;  // conversion from T to double?

The reason for asking is that it would be nice to avoid the following
ambiguity:

    void f(int x);     // parameter of a numerical type
    void f(char *s);   // parameter of a pointer type

    f(0);              // ambiguous call -- is 0 an int or a char*?

I would prefer that the default type for 0 be int, in accord with the
default type of functions and consts.  Then the call to f(0) would resolve
to calling f(int) and there would be no ambiguity.  It would of course
still be possible to call f(char*) via an explicit cast or, more palatibly,
by declaring a const null pointer of the appropriate type, e.g.,

    const char *NULLSTRING = 0;

    f(NULLSTRING);

Unfortunately, we'd have to augment the rules for disambiguating overloaded
functions described in section 13.2 of the ARM (pp. 312ff of the American
edition).  There are currently five rules.  I'd add the conversion of "0"
to "null pointer" to rule 3, on standard conversions.

I suspect the matter is substantially more complicated and subtle than I've
described here.  Comments?

Scott


-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."

steve@taumet.com (Stephen Clamage) (05/07/91)

sdm@cs.brown.edu (Scott Meyers) writes:

>What is the type of the constant "0", independent of any context?

A literal zero has type int.  It can also serve as a null pointer constant
when initializing a pointer.

	int i = 0;	// 0 has type int
	double d = 0;	// 0 implicitly converted to type double
	T* t = 0;	// 0 implicitly converted to type T*
	T* u = i;	// illegal, since i is not a null pointer constant

>The reason for asking is that it would be nice to avoid the following
>ambiguity:

>    void f(int x);     // parameter of a numerical type
>    void f(char *s);   // parameter of a pointer type
>    f(0);              // ambiguous call -- is 0 an int or a char*?

This is not ambiguous.  The zero is an exact match to f(int), but
requires a conversion to f(char*).  If your compiler calls it ambiguous,
this is a bug.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

juul@diku.dk (Anders Juul Munch) (05/07/91)

sdm@cs.brown.edu (Scott Meyers) writes:

>What is the type of the constant "0", independent of any context?  If there
>is such a default type, call it T.  Then are there any conversions in any
>of the following?

>    int i    = 0;  // conversion from T to int?
>    int *ip  = 0;  // conversion from T to int*?
>    double d = 0;  // conversion from T to double?

>The reason for asking is that it would be nice to avoid the following
>ambiguity:

>    void f(int x);     // parameter of a numerical type
>    void f(char *s);   // parameter of a pointer type

>    f(0);              // ambiguous call -- is 0 an int or a char*?
[stuff deleted]

Try: printf("%d,%d,%d\n", sizeof(int), sizeof(void*), sizeof(0));
on a system with different sizes for int and pointers. What you'll find is
that "0" is foremost an integer (which incidentally may be used in
place of a pointer :-).

But I wonder, if we have
	#define NULL 0
(which is ANSI C compliant, I don't know if C++ is any different), then
f(NULL) would call f(int)?! This seems highly unreasonable to me, and it
looks like yet another good reason why the implicit conversion of 0 to the
null pointer should be disallowed. 
Instead, NULL should be used whenever a null pointer is needed. NULL being
defined as
	#define NULL ((void*)0)
And
	int* ip = 0;
would then be illegal, and replaced by
	int* ip = NULL;


-- Anders Munch

chip@tct.com (Chip Salzenberg) (05/10/91)

According to juul@diku.dk (Anders Juul Munch):
>But I wonder, if we have
>	#define NULL 0
>(which is ANSI C compliant, I don't know if C++ is any different), then
>f(NULL) would call f(int)?! This seems highly unreasonable to me ...

That's the fact, Jack.  When in doubt, cast.

>looks like yet another good reason why the implicit conversion of 0 to the
>null pointer should be disallowed. 

Too late for that; implicit conversion of 0 to a pointer isn't even a
C++ invention.  As an ANSI C feature, I doubt it will disappear.

>Instead, NULL should be used whenever a null pointer is needed. NULL being
>defined as
>	#define NULL ((void*)0)
>And
>	int* ip = 0;
>would then be illegal, and replaced by
>	int* ip = NULL;

Sorry, that won't work.  The ARM explicitly disallows automatic
(castless) conversion of a |void*| to another pointer type.
-- 
Brand X Industries Sentient and Semi-Sentient Being Resources Department:
        Because Sometimes, "Human" Just Isn't Good Enough [tm]
     Chip Salzenberg         <chip@tct.com>, <uunet!pdn!tct!chip>

horstman@mathcs.sjsu.edu (Cay Horstmann) (05/10/91)

In article <1991May7.162035.9247@odin.diku.dk> juul@diku.dk (Anders Juul Munch) writes:
>
>But I wonder, if we have
>	#define NULL 0
>(which is ANSI C compliant, I don't know if C++ is any different), then
>f(NULL) would call f(int)?! This seems highly unreasonable to me, and it
>looks like yet another good reason why the implicit conversion of 0 to the
>null pointer should be disallowed. 
>Instead, NULL should be used whenever a null pointer is needed. NULL being
>defined as
>	#define NULL ((void*)0)
>And
>	int* ip = 0;
>would then be illegal, and replaced by
>	int* ip = NULL;
>
Beware of DOS header files that define NULL as 0L in the large memory
model!!! 0L is NOT convertible into a pointer. I got bitten by that one
when switching from Glockenspiel to Borland C++

Cay

tmb@ai.mit.edu (Thomas M. Breuel) (05/10/91)

In article <282980FB.6AB7@tct.com> chip@tct.com (Chip Salzenberg) writes:
   According to juul@diku.dk (Anders Juul Munch):
   >But I wonder, if we have
   >	#define NULL 0
   >(which is ANSI C compliant, I don't know if C++ is any different), then
   >f(NULL) would call f(int)?! This seems highly unreasonable to me ...

   That's the fact, Jack.  When in doubt, cast.

   >looks like yet another good reason why the implicit conversion of 0 to the
   >null pointer should be disallowed. 

   Too late for that; implicit conversion of 0 to a pointer isn't even a
   C++ invention.  As an ANSI C feature, I doubt it will disappear.

A possible fix to this mess might be to introduce a new value "nil"
that behaves mostly like "0", but is not an integer.

jerbil@ultra.com (Joseph Beckenbach {Adapter Software Release Engr}) (05/10/91)

	In his article Thomas M. Breuel <tmb@ai.mit.edu> writes
concerning implicit conversion of 0 to types, or lack of such conversion.
>A possible fix to this mess might be to introduce a new value "nil"
>that behaves mostly like "0", but is not an integer.

	I've stopped using 0 (as pointer) and NULL directly in my C code, 
and have finessed the problem with

#define NIL(type)	((type)NULL)

For me it's the easiest solution, since I tend not to think of a generic
'nil' pointer but of a 'nil pointer of type T'.

	What other reasonable schemes can be used for the same effect?

		Joseph Beckenbach
-- 
Joseph Beckenbach	jerbil@ultra.com		VEGGIES FOREVER!
	work 408-922-0100 x246

chip@tct.com (Chip Salzenberg) (05/14/91)

According to tmb@ai.mit.edu (Thomas M. Breuel):
>A possible fix to this mess might be to introduce a new value "nil"
>that behaves mostly like "0", but is not an integer.

I like it.  It's too late to save ANSI C, but C++ could finally
provide the vehicle to end the NULL wars.
-- 
Brand X Industries Custodial, Refurbishing and Containment Service:
         When You Never, Ever Want To See It Again [tm]
     Chip Salzenberg   <chip@tct.com>, <uunet!pdn!tct!chip>