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