---------- Forwarded message ----------
Date: Thu, 28 Feb 2002 13:12:03 +1300 (NZDT)
From: Richard A. O'Keefe <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Subject: Re:  Overzealous sign checking? (fwd)

        unsigned short a = 1;
        long b = 2;

        if (a < b) return FALSE;

        blah.c(10): Operands of < have incompatible types (unsigned short int, long 
int): a < b
          To ignore signs in type comparisons use +ignoresigns

        Now while this is clearly true, we would argue it's also harmless IFF
        we can assume an ANSI compiler.

The rules for mixing signed and unsigned arithmetic are sufficiently
confusing, especially if you have been using C since K&R days, that
mixing is best avoided, except for cases like "a = 1;".

Take this little program:
#include <stdio.h>

int main(void) {
    unsigned short a =  1;
    long           b = -1;

    if (a < b) {
        printf("What a surprise!\n");
    } else {
        printf("Worked as expected.\n");
    }
    return 0;
}

The result I get depends on the options I pass to my compiler.
And rightly so, because ANSI changed the rules, and there's still
a bunch of pre-ANSI and half-ANSI code that relies on the old
rules.  (I still flinch when I recall my experience trying to
fix one such program.)

        The second edition of K&R says this:

        A6.1 Integral Promotion

        A character, a short integer, or an integer bit-field, all either
        signed or not, or an object of enumeration type, may be used in an
        expression whenever an integer may be used. If an int can represent
        all of the values of the original type, then the value is converted to
        int, otherwise the value is converted to unsigned int. This process is
        called integral promotion.

        Since all uint16 values are representable in an int32,

Who said short was 16 bits or long 32?  The keyboard I'm typing on is
part of a 64-bit workstation; the mail is going through another 64-bit
machine.  Also in my office I have a 486 box running MS-DOS 6, and oddly
enough, there's a program I'm revising that will have to run on that
machine (where int is 16 bits) as well as the 64-bit machines.  Note
that the rules for promoting unsigned short are *different* on these
machines, thanks to the lame-brained ANSI rules, because an int on the
MS-DOS box _can't_ represent all values of an unsigned short, while an
int on the 64-bit machines _can_.  (For the record, I have used C on a
36-bit machine.  I can't remember what unsigned short was, probably 18 bits.)

        I reckon this warning is not justified in this case.
        [He'd like to suppress it.]

So put in an explicit cast!

        unsigned short a = 1;
        long b = 2;

        if ((long)a < b) return FALSE;

This is a far simpler way to locally suppress the warning than
any alternative I can think of, and it has the benefit of making
your choice (convert to signed) really obvious.

        We'd like to turn +ignoresigns
        back on, because of course there are many times when it's telling us
        something important!

Like right here.  It is _not_ obvious to me what you want  a < b
to do when b is -1.  Put in the cast, and it's obvious to everyone,
including C compilers, whatever the size of int.


Reply via email to