Article View: comp.std.c
Article #3743Re: Semantics of relational operators
From: Mark Brader
Date: Wed, 16 Aug 1995 14:30
Date: Wed, 16 Aug 1995 14:30
111 lines
4903 bytes
4903 bytes
raine@ferndown.ate.slb.com writes:
> gcc issues the diagnostic "Semantics of <= have changed in ANSI C, please
> use explicit cast" for the following:
>
> unsigned short a = 0;
> long b = 0;
> if (a <= b) /* gcc expects explicit cast here */
>
> 6.3.8 seems to yield no information as to why a cast is desirable here.
The proper reference is to section 3.2.1.1 of the Rationale, corresponding
to 6.2.1.1 in the renumbered Standard.
I posted the following to comp.lang.c in August:
| > A C compiler gives for the statement
| > if (strlen (...) > 41) ...
| > the warning
| > semantics of ">" change in ANSI C: use explicit cast
| >
| > What does that mean?
|
| It means that the compiler is too stupid to tell that the expression 41,
| despite its type being int, could not possibly be negative. Ignore it.
In raine's example, though, there could be a real difference if short is
narrower% than int and b < 0.
| In a situation like THIS:
|
| extern unsigned short usvar;
| extern int ivar;
|
| if (usvar > ivar) /* A */
|
| the change would be important. The type "unsigned short" did not exist
| in K&R C, and when it was added to the language, different implementers
| made different choices as to whether to treat the above like
|
| if ((unsigned int) usvar > (unsigned int) ivar) /* U */
| or like
| if ((int) usvar > (int) ivar) /* V */
|
| which of course will have different results of ivar is negative.
|
| If int and short are the same width%, interpretation U always applies.
| But if int is wider than short, there are reasons for each choice;
| The common UNIX compilers for such machines followed interpretation U
| ("unsigned preserving"), but other compilers followed interpretation V
| ("value preserving").
|
| When the ANSI C standard was written, its writers chose value preserving.
| Thus, the meaning of code like A changed for people who had been used
| to unsigned preserving. They also specified that strlen(), which had
| returned int on most implementations, should now return size_t, which is
| some unsigned integer type. Thus, code that formerly was not like A,
| but which used strlen(), became like it -- something that likely would
| not have been feasible if they had chosen unsigned preserving.
In raine's example,
> unsigned short a = 0;
> long b = 0;
> if (a <= b) /* gcc expects explicit cast here */
if short is narrower% than int, then under the value preserving rules,
a will be promoted to int, then converted to long to match b, and the
comparison will be done in signed arithmetic. If short is the same
width% as int, then a will be converted to unsigned int, both a and
b will be converted to unsigned long, and the conversion will be done
in unsigned arithmetic. The latter conversions also apply if unsigned
preserving is in effect.
If b >= 0, the variation makes no difference. If b < 0, only value
preserving arithmetic has a chance of comparing the actual values of
the variables, though even it might not do so, depending on their sizes;
and this is the ANSI C "change" from unsigned preserving implementations.
If you actually want the comparison in signed arithmetic, use
if ((long) a <= b)
If you actually want unsigned arithmetic, use a cast to unsigned long.
| The compiler's warning, then, is a misguidedly terse attempt to warn
| you about all this.
|
| Incidentally, it wasn't only < whose semantics were standardized on
| value preserving in ANSI C. Almost all operators are affected. In
| particular, an expression like
|
| ivar + usvar
|
| was previously ambiguous in the same way and has been resolved in the
| same way. This means that that compiler logically ought to give you
| the same meaningless warning in the case of
|
| strlen (s) + 41
|
| as it does for the original line -- semantics of "+" have changed...
| I bet it doesn't, though.
% - This is a slight simplification, because I don't want to reactivate
the debate about bits not participating in a value.
--
Mark Brader | "A standard is established on sure bases, not capriciously
msb@sq.com | but with the surety of something intentional and of a logic
SoftQuad Inc. | controlled by analysis and experiment. ... A standard is
Toronto | necessary for order in human effort." -- Le Corbusier
This article is in the public domain.
Technical Details
Message-ID:
<1995Aug16.143035.3322@sq.com>Path:
arc1-ca.pugleaf.net!howland.reston.ans.net!torn!sq!msbReferences:
<40ses9$5o6@sndsu1.sedalia.sinet.slb.com>Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c Path: arc1-ca.pugleaf.net!howland.reston.ans.net!torn!sq!msb From: msb@sq.com (Mark Brader) Subject: Re: Semantics of relational operators Message-ID: <1995Aug16.143035.3322@sq.com> Organization: SoftQuad Inc., Toronto, Canada References: <40ses9$5o6@sndsu1.sedalia.sinet.slb.com> Date: Wed, 16 Aug 1995 14:30:35 GMT