constant signed/unsigned comparison warning
Olivier Galibert
Olivier.Galibert@mines.u-nancy.fr
Wed Sep 24 08:11:00 GMT 1997
On Wed, Sep 24, 1997 at 03:09:30PM +0200, Matthias Urlichs wrote:
> Hi,
>
> Thomas Koenig wrote:
> >Matthias Urlichs wrote:
> >> And because GCC knows how to figure out the size of the struct, but then
> >> forgets to check if the high bit of that size is set (otherwise you cannot
> >> run into a problem in the first place).
> >
> >The problem is that, for all the compiler knows, this might be
> >equivalent to
> >
> > int i = random_func_which_returns_minus_10000();
>
> We were talking about sizeof(). Gcc knows that sizeof 'returns' a smallish
> integer (it's a constant, after all). Smallish integers on one side of a
> comparison can be either signed or unsigned depending on the other side of
> the comparison. You don't see a warning when you compare an integer, be it
> signed or unsigned, with the constant 100...
AFAIK, you're wrong there. The point is, the constant 100 is signed unless you
write it 100U. The case we're dealing with here is:
signed int a;
unsigned int b;
if(a<b) {...}
I don't have the C standard handy but I know that the C++ cd2 is similar to it
in this respect. It says:
9 Many binary operators that expect operands of arithmetic or enumera-
tion type cause conversions and yield result types in a similar way.
The purpose is to yield a common type, which is also the type of the
result. This pattern is called the usual arithmetic conversions,
which are defined as follows:
[lots of irrelevant cases]
--Otherwise, if either operand is unsigned, the other shall be con-
verted to unsigned.
Which means 'a' _must_ be converted to unsigned int. This conversion is
defined as:
2 If the destination type is unsigned, the resulting value is the least
unsigned integer congruent to the source integer (modulo 2n where n is
the number of bits used to represent the unsigned type). [Note: In a
two's complement representation, this conversion is conceptual and
there is no change in the bit pattern (if there is no truncation). ]
The net effect of that is that:
if( -1 < 100U) {...}
_must_ be treated as:
1- Converting -1 to unsigned, which means 4294967295
2- Comparing the result with 100
which means the test _must_ yield false.
Conclusion: the code is broken, fix it. Gcc implementors, please do not
remove the warning, this bug is insidious.
Please note that this has nothing to do about the smallishness of the
unsigned integer. Implicitely converting it to signed is explicitely
disallowed.
OG.
PS: The possible brokeness of the standard itself is out of scope. The
code is broken. If it works, it is a compiler bug which should be
fixed.
More information about the Gcc
mailing list