[comp.std.c] Non-Portable pointer assignment?

mcdaniel@adi.com (Tim McDaniel) (06/06/91)

Followups directed to comp.std.c.

In article <1991Jun5.150527.22942@klaava.Helsinki.FI>
wirzeniu@klaava.Helsinki.FI (Lars Wirzenius) writes:

   Actually, 'x' is an int. (Being picky, I know.)

It's not "picky"; it can be crucial.  I decided to use
`self-documenting code', as it were, to show the space necessary for
nul bytes, ',' between concatenated strings, and such.

   p = malloc(strlen(s) + sizeof '\0');

It took me a while to figure out that I ought to change it to

   p = malloc(strlen(s) + sizeof (char) '\0');

because sizeof '\0' is 4 on our machines.  Because of FlexeLint (with
a very rare bug), our non-ANSI compilers, and the fact that it's
actually our own MEMmalloc, I actually had to write something like

   p = MEMmalloc((ulong) strlen(s) + (ulong) sizeof ((char) '\0'));

Gak!  I just realized, however, that

   p = malloc(strlen(s) + sizeof "");

should work for ANSI environments.

So why in creation was 'x' ever specified to be int?  Why not char,
with the usual widening in expressions?  And why did X3J11 specify
that the types of enum constants were int, rather than the same type
as the underlying enum type?  It is HIGHLY disconcerting to discover
that a "character constant" is not of type char, and an "enumeration
constant" is not of its enumerated type.

--
   "Of course he has a knife; he always has a knife.  We all have knives.
   It's 1183 and we're barbarians."
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/07/91)

In article <MCDANIEL.91Jun6111329@dolphin.adi.com> mcdaniel@adi.com (Tim McDaniel) writes:

>So why in creation was 'x' ever specified to be int?  Why not char,
>with the usual widening in expressions?

The answer is very ugly.  Some old programs took advantage of being able
to put more than one char in a char constant, since it was really an int.
Anyway, no one ever thought of asking "sizeof" of a char constant because
"sizeof" of a char was always 1 anyway, and no one multiplied by something
they knew was 1.  And outside of "sizeof", you can't distinguish one kind
of integer constant from another.  For example, there's no way of specifying
a short constant.  (Well, you can specify a long, but that's because ints
didn't automatically promote to longs.  And you can now specify unsigned,
but this didn't break any existing code, I think.)

>And why did X3J11 specify that the types of enum constants were int,
>rather than the same type as the underlying enum type?

Actually this is one of the few consistent things around.  For example,
3 is not a char even though it fits in one, and 3 is not a short even
though it fits in one.

If you really want to be horrified, I cannot find any requirement that
an enumeration type actually be able to hold all of the values of its
members.  For example, in
  enum what_type { a = -1, b = 1000000 } what;
well enum what_type might be compatible with unsigned short, and what
might be unable to hold the value of a or b....
--
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.

mcdaniel@adi.com (Tim McDaniel) (06/07/91)

In article <1991Jun7.013605.728@tkou02.enet.dec.com> diamond@jit533.swstokyo.dec.com (Norman Diamond) writes:

   The answer is very ugly.  Some old programs took advantage of being able
   to put more than one char in a char constant, since it was really an int.

I would have been quite content to have seen the types and sizes of
'xy' and 'x' differ.  (The 'xy' implementation-defined semantics could
have been tighted a bit, too.  If sizeof (T) is N, then other parts of
the C standard require that N characters fit into T.  Some wording
could have been found to require that multiple-byte character
constants have up to N characters placed in distinct bytes.  Or maybe
they just should have been forbidden -- they're fairly useless
anyway.)

   Actually [enum constants are int] is one of the few consistent
   things around.  For example, 3 is not a char even though it fits in
   one, and 3 is not a short even though it fits in one.

I've never declared 3 to be a value of a type.  Enumeration constants,
however, *are* declared to be within a particular enumeration type.

--
   "Of course he has a knife; he always has a knife.  We all have knives.
   It's 1183 and we're barbarians."
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

henry@zoo.toronto.edu (Henry Spencer) (06/07/91)

In article <1991Jun7.013605.728@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>If you really want to be horrified, I cannot find any requirement that
>an enumeration type actually be able to hold all of the values of its
>members...

It's worse than that.  Recently it was pointed out that a named enumeration
type is in scope as soon as its name is seen, and since there is no provision
for incomplete enumerated types, that means that `sizeof(enumtype)' is legal
before the members have been seen... so the size of the type cannot depend
on the values of the members!!  (In X3J11's defence, this probably was not
deliberate.)
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

gwyn@smoke.brl.mil (Doug Gwyn) (06/08/91)

In article <MCDANIEL.91Jun6111329@dolphin.adi.com> mcdaniel@adi.com (Tim McDaniel) writes:
>It is HIGHLY disconcerting to discover that a "character constant" is not of
>type char, and an "enumeration constant" is not of its enumerated type.

Disconcerting or no, both kinds of constants have been of type int since
they were first introduced.  (I.e. X3J11 didn't invent this.)

gwyn@smoke.brl.mil (Doug Gwyn) (06/08/91)

In article <1991Jun7.161752.9625@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
-It's worse than that.  Recently it was pointed out that a named enumeration
-type is in scope as soon as its name is seen, and since there is no provision
-for incomplete enumerated types, that means that `sizeof(enumtype)' is legal
-before the members have been seen... so the size of the type cannot depend
-on the values of the members!!  (In X3J11's defence, this probably was not
-deliberate.)

I'm not sure X3J11 would agree with the above interpretation.
If anybody really cares about this, they should request a formal ruling on it.

henry@zoo.toronto.edu (Henry Spencer) (06/10/91)

In article <16359@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>-It's worse than that.  Recently it was pointed out that a named enumeration
>-type is in scope as soon as its name is seen, and since there is no provision
>-for incomplete enumerated types, that means that `sizeof(enumtype)' is legal
>-before the members have been seen... so the size of the type cannot depend
>-on the values of the members!!  (In X3J11's defence, this probably was not
>-deliberate.)
>
>I'm not sure X3J11 would agree with the above interpretation.

What part of it do you think they would disagree with?  I see no
"interpretation" involved.
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

gwyn@smoke.brl.mil (Doug Gwyn) (06/10/91)

In article <1991Jun9.224624.3859@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
-In article <16359@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
->-It's worse than that.  Recently it was pointed out that a named enumeration
->-type is in scope as soon as its name is seen, and since there is no provision
->-for incomplete enumerated types, that means that `sizeof(enumtype)' is legal
->-before the members have been seen... so the size of the type cannot depend
->-on the values of the members!!  (In X3J11's defence, this probably was not
->-deliberate.)
->I'm not sure X3J11 would agree with the above interpretation.
-What part of it do you think they would disagree with?  I see no
-"interpretation" involved.

For one, the claim that "there is no provision for incomplete enumerated types".
It seems to me that the case in point provides a perfect counterexample.

henry@zoo.toronto.edu (Henry Spencer) (06/11/91)

In article <16369@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>...the claim that "there is no provision for incomplete enumerated types".
>It seems to me that the case in point provides a perfect counterexample.

You're confusing need with provision.  The case in point provides an
example of a *need* for incomplete enumerated types.  However, the standard
does not provide such a feature.  Indeed, wording in at least one place
(I'm at Usenix and don't have my copy handy) indicates clearly that X3J11
specifically thought that there was no such thing.
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

hansen@pegasus.att.com (Tony L. Hansen) (06/18/91)

< From: mcdaniel@adi.com (Tim McDaniel)
< I would have been quite content to have seen the types and sizes of
< 'xy' and 'x' differ.

C++ has taken this tack: the type of 'x' is char while the type of 'xy' is
int. It gives very nice properties when dealing with function and operator
overloading.

					Tony Hansen
			    hansen@pegasus.att.com, tony@attmail.com
				att!pegasus!hansen, attmail!tony