> > > > ((int)val & 0x100) == 0
> > > > (if 'val' is signed and negative, it'll be sign-extended, so bits
> > > > above the low 8 will be set. otherwise those bits will be zero.)
> > > If we were willing to require ANSI C,
> > > (signed char)val >= 0
> > No it wouldn't, because that would _force_ all chars to be signed,
> > even if the implementation's chars are by default unsigned.
>
> Doh! I misunderstood the intent of the original expression.
> In that case, I think that
> (int)val >= 0
> does the right thing in every useful case: if val is an unsigned type
> strictly narrower than int, the result of casting to int will still be a
> positive small integer; if val is a signed type strictly narrower than
> int, then (int)val is negative if and only if val is negative. Plus, it
> doesn't misfire if char is wider than 8 bits (as if the code wrapped around
> that line wouldn't!), and it more directly expresses the intent.
Correct.
However, the original goal was to come up with an expression which
yields the correct result _and_ which avoids the gcc "comparison is
always 1 due to limited range of data type" warning.
(val >= 0) yields the correct result, but causes that warning.
((int)val >= 0) yields the correct result, but also causes that
warning.
(((int)val & 0x100) == 0) also yields the correct result (for machines
where char is 8 bits -- i.e. all machines that NetBSD supports), but
does not cause that warning. The expression is still always true on
unsigned-char machines, but gcc isn't sophisticated enough to catch
it.
I'd love to hear a better suggestion, but... 8-)
chris