[comp.std.c] How soon can `sizeof

rfg@lupine.ncd.com (Ron Guilmette) (05/12/91)

I may have asked this question once already (long ago).  If so I apologize.
I forgot the answer.

Are either or both of these examples legal?

enum E { red, green = sizeof (enum E), blue };

struct S { int i; int j : sizeof (struct S); int k; };

henry@zoo.toronto.edu (Henry Spencer) (05/14/91)

In article <5506@lupine.NCD.COM> rfg@lupine.ncd.com (Ron Guilmette) writes:
>Are either or both of these examples legal?
>
>enum E { red, green = sizeof (enum E), blue };
>struct S { int i; int j : sizeof (struct S); int k; };

I think neither.

In the first one, the argument of sizeof is meaningless, because E is not
declared until the end of the brace-enclosed list.  Enums, unlike structs
and unions, cannot be incomplete types.

In the second example, the struct type is incomplete until the
closing brace.  ANSI C is rather vague about where incomplete types can
be used, saying only "when the size of an object of the specified type
is not needed", with no explanation of what that *means*, but sizeof is
the one clear situation.
-- 
And the bean-counter replied,           | Henry Spencer @ U of Toronto Zoology
"beans are more important".             |  henry@zoo.toronto.edu  utzoo!henry

blodgett@apollo.HP.COM (Bruce Blodgett) (05/17/91)

In article <1991May13.175830.7143@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In article <5506@lupine.NCD.COM> rfg@lupine.ncd.com (Ron Guilmette) writes:
>>Are either or both of these examples legal?
>>
>>enum E { red, green = sizeof (enum E), blue };
>>struct S { int i; int j : sizeof (struct S); int k; };
>
>I think neither.
>
>In the first one, the argument of sizeof is meaningless, because E is not
>declared until the end of the brace-enclosed list.  Enums, unlike structs
>and unions, cannot be incomplete types.

Section 3.1.2.1 states:
"enumeration tags have scope that begins just aftert the appearance of
the tag in a type specifier that declares the tag."

So enum tag E is in scope at the sizeof(enum E).

Section 3.3.3.4 lists the following Constraint:
"The sizeof operator shall not be applied to an expression that has ...
an incomplete type"

The question becomes, "does enum E have incomplete type inside its
enumerator-list?"

Section 3.1.2.5 defines incomplete types as:
"types that describe objects but lack information needed to determine
their sizes".

The question becomes, "does enum E lack information needed to
determine its size inside its enumerator-list?"

Section 3.5.2.2 states:
"Each enumerated type shall be compatible with an integer type; the
choice of type is implementation-defined."

The implementation could choose exactly one integral type with which
to make all enumerated types compatible.  In this case, enum E has
enough information to determine its size inside its enumerator-list.

Alternately, the implementation could tailor each enumerated type to
be the smallest integral type sufficient to store any of its member's
values (to save on disk space).  In this case, enum E does NOT have
enough information to determine its size inside its enumerator-list.

Therefore the definition
   enum E { red, green = sizeof (enum E), blue };

relies upon implementation-defined behavior.
Bruce Blodgett
blodgett@apollo.hp.com
(508) 256-0176 x4037

henry@zoo.toronto.edu (Henry Spencer) (05/19/91)

In article <519a28cf.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
>>>enum E { red, green = sizeof (enum E), blue };
>Section 3.1.2.1 states:
>"enumeration tags have scope that begins just aftert the appearance of
>the tag in a type specifier that declares the tag."

Hmm, you're right, I missed that one.

>The question becomes, "does enum E have incomplete type inside its
>enumerator-list?"
>
>Section 3.1.2.5 defines incomplete types as:
>"types that describe objects but lack information needed to determine
>their sizes".

No, that phrase appears to be an informal description rather than a precise
definition.  The standard never defines what information is needed to
determine sizes; it merely describes two specific constructs (array without
dimension and struct/union without declaration list) that generate incomplete
types.  In fact, in the discussion of tags (3.5.2.3) there is a footnote
indicating that the committee thought it was clear that enums could not
be incomplete.  Certainly there is no discussion for enum analogous to
that for struct/union about how an incomplete type comes into existence.

(That same footnote indicates that they thought other types could not depend
on the details of the declaration of an enumerated type, which is, of course,
wrong when sizeof comes into the picture.)

I don't think the matter can be settled cleanly by reference to the existing
standard.  Some ambitious soul might want to submit a request for a formal
interpretation.  However, there does seem to be trouble lurking here for an
implementation that tries to custom-tailor the sizes of enumerated types.

>Therefore the definition
>   enum E { red, green = sizeof (enum E), blue };
>relies upon implementation-defined behavior.

No, it relies on behavior that is not clearly specified by the standard.
"Implementation defined" has a specific meaning in ANSI-C-speak, and this
isn't it.  It would probably be better to assume that the relevant behavior
is undefined, meaning that anything can happen and users should avoid the
construct entirely.
-- 
And the bean-counter replied,           | Henry Spencer @ U of Toronto Zoology
"beans are more important".             |  henry@zoo.toronto.edu  utzoo!henry

enag@ifi.uio.no (Erik Naggum) (05/20/91)

Ron Guilmette writes:
|
|   Are either or both of these examples legal?
|
|   enum E { red, green = sizeof (enum E), blue };

I think I may be missing something vital in your question.

What is "sizeof (enum E)" supposed to return if not the same as
"sizeof (int)"?

</Erik>
--
Erik Naggum             Professional Programmer            +47-2-836-863
Naggum Software             Electronic Text            <enag@ifi.uio.no>
0118 OSLO, NORWAY       Computer Communications      <erik@naggum.uu.no>

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/20/91)

In article <ENAG.91May20004919@maud.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes:
>Ron Guilmette writes:
>>   enum E { red, green = sizeof (enum E), blue };
>
>What is "sizeof (enum E)" supposed to return if not the same as
>"sizeof (int)"?

sizeof (short), sizeof (long), or sizeof (other_integral_type_which_the_\
implementation_is_allowed_to_define_even_though_portable_programs_cannot_\
directly_name_this_type)
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

enag@ifi.uio.no (Erik Naggum) (05/20/91)

Erik Naggum writes:
|
|   What is "sizeof (enum E)" supposed to return if not the same as
|   "sizeof (int)"?

Norman Diamond writes:
|
|   sizeof (short), sizeof (long), or sizeof (other_integral_type_which_the_\
|   implementation_is_allowed_to_define_even_though_portable_programs_cannot_\
|   directly_name_this_type)

Right.  There's a subtle difference between the type of enumerators
and the enumeration type itself.  Section 3.5.2.2 of dpANS of 1/11/88
(sorry, I have the proper standard at my office) specifies that the
former have type int, while the enumerated type "shall be compatible
with an integer type; the choice of type is implementation-defined".
(Why this is so escapes me.)

</Erik>
--
Erik Naggum             Professional Programmer            +47-2-836-863
Naggum Software             Electronic Text            <enag@ifi.uio.no>
0118 OSLO, NORWAY       Computer Communications      <erik@naggum.uu.no>

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/21/91)

Erik Naggum writes:
>|   What is "sizeof (enum E)" supposed to return if not the same as
>|   "sizeof (int)"?
Norman Diamond writes:
>|   sizeof (short), sizeof (long), or sizeof (other_integral_type...)
Erik Naggum:
>Right.  There's a subtle difference between the type of enumerators
>and the enumeration type itself. ... the former have type int, while
>the enumerated type "shall be compatible with an integer type; the choice
>of type is implementation-defined".  (Why this is so escapes me.)

Variables can be declared with the enumeration type, and their storage
requirements are determined accordingly.  But enumerators are just constants.
The constants 5200 and 'x', for example, have type int, even though they can
fit in shorts; but they're just constants and aren't necessarily stored.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.