Topic: Enumerated type converted to pointer? Legal?


Author: phalpern@truffle.ultranet.com (Pablo Halpern)
Date: 1996/03/28
Raw View
kanze@gabi-soft.fr (J. Kanze) wrote:

>The error may be historically conditioned.  As I interpret the C
>standard, an enumerated constant has type int, and a constant integral
>expression which evalutates to 0 is a null pointer.  Even in the ARM,
>however, ``An enumeration is a distinct integral type.''

That begs the question, however, whether being an integral type with
constant value zero is sufficient to allow assignment to a pointer.
Let me illustrate:

    void *p = 0;

This is definately legal. The pointer can be initialized or assigned
from the literal.

    const int nil1 = 0;
    void *p = nil1;

    const unsigned char nil2 = 0;
    p = nil2;

Is this legal? I believe all of the above is legal, though IMO it
shouldn't be (see below)

    enum ptrNil { nil3 };
    void *p = nil3;

You are claiming that this is not legal because nil3 is of type ptrNil
which is not compatable with the type of p. However, I fail to see how
nil3 is different from nil1 and nil2 in this respect. All are `integral'
types with value zero.

I agree that the assignment of nil3 to p *should not* be legal because
nil3 is not a pointer type. But by the same logic, neither should the
assignments to nil1 and nil2 be legal. IMO it would be simplest to
disallow implicit conversion from any integral type to a pointer type
*except* in the case of literal zero. I don't think adding this
prohibition would break much code. <stdlib> defines NULL as

   #define NULL 0

so any code that uses NULL or 0 for the null pointer would still work.
Perhaps to cover most of the rest of the cases we could add the rule
that any constant expression with value `(void *) 0' can be converted to
any pointer type without a cast. This would allow nice constructions
like:

   void *const nil = 0;

In summary, I think that using a zero enumeration as a null pointer *is*
currently legal, but shouldn't be.

-------------------------------------------------------------
Pablo Halpern                   phalpern@truffle.ultranet.com

I am self-employed. Therefore, my opinions *do* represent
those of my employer.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/03/30
Raw View
In article <315a9640.1061096@news.ultranet.com>
phalpern@truffle.ultranet.com (Pablo Halpern) writes:

|> kanze@gabi-soft.fr (J. Kanze) wrote:

|> >The error may be historically conditioned.  As I interpret the C
|> >standard, an enumerated constant has type int, and a constant integral
|> >expression which evalutates to 0 is a null pointer.  Even in the ARM,
|> >however, ``An enumeration is a distinct integral type.''

|> That begs the question, however, whether being an integral type with
|> constant value zero is sufficient to allow assignment to a pointer.

|> Is this legal? I believe all of the above is legal, though IMO it
|> shouldn't be (see below)

|>     enum ptrNil { nil3 };
|>     void *p = nil3;

|> You are claiming that this is not legal because nil3 is of type ptrNil
|> which is not compatable with the type of p. However, I fail to see how
|> nil3 is different from nil1 and nil2 in this respect. All are `integral'
|> types with value zero.

Before going any farther, several people have already pointed out my
mistake to me in private email.  Basically, I missed the fact that when
enum's were made full types, the definition of integral constant was
also extended to include them.  So the above is legal, and nil3 is a
legal null pointer.  (In C, it was definitly legal, because the type of
nil3 was expressedly int.  I mistakenly supposed that because C++
changed this type, it had also rendered the above illegal.)

I, for one, wouldn't object if the definition of a null pointer were
further restricted to limit it to only {int, unsigned int, long,
unsigned long}.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/03/22
Raw View
In article <4hobji$mco@netlab.cs.rpi.edu> bstowers@pobox.com (Brad
Stowers) writes:

 [I've stripped all but comp.std.c++ out of the newsgroups line.  In
 general, it is very awkward for the moderators if you cross-post to
 several moderated groups, and comp.std.c++ seemed the most
 appropriate.]

|> #include <stdio.h>

|> typedef enum { mdType1, mdType2, mdType3 } myType;

|> void FooBar(int x,
|>             int* y,
|>             myType type = mdType1)
|> {
|>   printf("x=%i\ny=%p\ntype=%type\n", x, y, type);
                                           ^

Just a warning: this is undefined behavior, although it will work on a
lot of machines.  You must cast any parameter corresponding to a `%p' to
void* (if it isn't void* already).

Also: what is %type?

(The above sound like two very good reasons for switching to iostream to
me.)

|> }

|> main()
|> {
|>   int x = 10;
|>   int* y = &x;
|>   FooBar(x, y, mdType2);
|>   FooBar(x, mdType1);
|> }

|> ------------------EOF------------------------------

|> Compile and run the above program.  Is it just me, or should the last line
|> of the main() function ( FooBar(x, mdType1); ) have caused a type mismatch
|> error?

Definitly.

|> I think I know why it didn't:  mdType1 evaluates to an integer with
|> a value of 0, which is a valid value to pass as a pointer.  In support of
|> this theory, the line:

|>   FooBar(x, mdType2);

|> will not compile, but rather generates the expected type mismatch error.
|> Obviously, the work-around is simple:

|>   typedef enum { mdType1 = 1, mdType2, mdType3 } myType;

|> While this will solve the problem, I really think that it is the compiler's
|> job to see that mdType1 does not evaluate to the proper type no matter what
|> it's internal representation might be.

Correct.  There is nothing in the standard that allows converting an
enum to a pointer, irrespective of the numerical value of the enum.

|> I have verified that this happens on both Borland and Symantec compilers.
|> Can anyone verify it on Watcom and Microsoft for me?

No.  On a Sun, however, g++ (2.7.2) gives the correct error message.
Sun CC (4.1) has the same error as Borland and Symantec.

The error may be historically conditioned.  As I interpret the C
standard, an enumerated constant has type int, and a constant integral
expression which evalutates to 0 is a null pointer.  Even in the ARM,
however, ``An enumeration is a distinct integral type.''

(In fact, the question is less clear that the above would make it
appear.  While the C standard definitly says that an enumerator has type
int, it also implies that the enum statement itself defines a new
distinct type, ``compatible with an integer type.''  And while in the
absense of a definite statement to the contrary in the ARM, and the
insistence that the enumeration is a distinct type, I think that the
intent is clear that the enumerator should have the same type as the
enumeration, rather than int, there are no explicit words to this
effect.)

This is all passe, however.  From the Jan., 1996 draft standard: ``The
type of an enumerator is its enumeration.''  You cannot get any clearer
than that.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]