warning: comparison is always true due to limited range of data type

Discussion in 'C Programming' started by phil-news-nospam@ipal.net, Oct 26, 2009.

  1. Guest

    I have the following expression coded in a macro:

    ((((__typeof__((x)))0) - ((__typeof__((x)))1)) < ((__typeof__((x)))0))

    It uses GCC's extension __typeof__() but I don't think that's an issue.
    This expression is intended to evaluate true whenever x is a signed integer
    and false whenever x is an unsigned integer. The purpose is to give the
    compiler a good chance at optimizing out the expressions that follow in the
    ?: trinary operator. Since this expression is strictly a constant, it should
    be easy to detect that only one or the other of the ?: expressions is needed.

    When I use int, long, or long long, either signed or unsigned, this compiles
    without any warning. When I use signed short, it is also without warning.
    But when I use unsigned short, I get the warning.

    Clearly, the result will be out of range for unsigned, although it will be
    converted back into range. What puzzles me more than getting it for unsigned
    short is NOT getting it for unsigned int. That doesn't seem consistent. Is
    there something special in the standard that would make such an expression,
    or the conversion involved in that arithmetic, be different for int compared
    to short?

    Here's the expression with hard coded types for easier reading (although for
    no practical purpose):

    ((signed short)0) - ((signed short)1) < ((signed short)0)
    ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)

    ((signed int)0) - ((signed int)1) < ((signed int)0)
    ((unsigned int)0) - ((unsigned int)1) < ((unsigned int)0)

    --
    -----------------------------------------------------------------------------
    | Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
    | (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
    -----------------------------------------------------------------------------
    , Oct 26, 2009
    #1
    1. Advertising

  2. Ben Pfaff Guest

    writes:

    > ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)


    I don't think that this does what you want. Due to the way that
    arithmetic promotions work, I think that it ordinarily evaluates
    to -1 < 0, which evaluates to 1.

    Indeed, on my system:

    blp@blp:~(0)$ cat > tmp.c
    #include <stdio.h>
    int
    main(void)
    {
    printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
    return 0;
    }
    blp@blp:~(0)$ gcc tmp.c
    blp@blp:~(0)$ ./a.out
    1
    blp@blp:~(0)$
    --
    Ben Pfaff
    http://benpfaff.org
    Ben Pfaff, Oct 26, 2009
    #2
    1. Advertising

  3. Ben Pfaff <> writes:
    > writes:
    >
    >> ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)

    >
    > I don't think that this does what you want. Due to the way that
    > arithmetic promotions work, I think that it ordinarily evaluates
    > to -1 < 0, which evaluates to 1.
    >
    > Indeed, on my system:
    >
    > blp@blp:~(0)$ cat > tmp.c
    > #include <stdio.h>
    > int
    > main(void)
    > {
    > printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
    > return 0;
    > }
    > blp@blp:~(0)$ gcc tmp.c
    > blp@blp:~(0)$ ./a.out
    > 1
    > blp@blp:~(0)$


    Here's something that does what you probably want:

    #include <stdio.h>
    int main(void)
    {
    if ((unsigned short)-1 < (unsigned short)0) {
    puts("unsigned short is a signed type (?!?!?!)");
    }
    else {
    puts("unsigned short is an unsigned type");
    }
    return 0;
    }

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 26, 2009
    #3
  4. Eric Sosman Guest

    Re: warning: comparison is always true due to limited range of datatype

    Keith Thompson wrote:
    >
    > #include <stdio.h>
    > int main(void)
    > {
    > if ((unsigned short)-1 < (unsigned short)0) {
    > puts("unsigned short is a signed type (?!?!?!)");
    > }
    > else {
    > puts("unsigned short is an unsigned type");
    > }
    > return 0;


    Is the second cast necessary? (Have I missed something,
    yet again?)

    --
    Eric Sosman
    lid
    Eric Sosman, Oct 26, 2009
    #4
  5. Stefan Ram Guest

    Eric Sosman <> writes:
    >>if ((unsigned short)-1 < (unsigned short)0) {

    >Is the second cast necessary? (Have I missed something,
    >yet again?)


    Without the second cast, the first operand will be
    converted (promoted) to »int«, but since it already
    has a positive value, the result should be the same.
    Stefan Ram, Oct 26, 2009
    #5
  6. Guest

    On Mon, 26 Oct 2009 11:32:44 -0700 Ben Pfaff <> wrote:

    | writes:
    |
    |> ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)
    |
    | I don't think that this does what you want. Due to the way that
    | arithmetic promotions work, I think that it ordinarily evaluates
    | to -1 < 0, which evaluates to 1.
    |
    | Indeed, on my system:
    |
    | blp@blp:~(0)$ cat > tmp.c
    | #include <stdio.h>
    | int
    | main(void)
    | {
    | printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
    | return 0;
    | }
    | blp@blp:~(0)$ gcc tmp.c
    | blp@blp:~(0)$ ./a.out
    | 1
    | blp@blp:~(0)$

    Oh ... I got caught by that one. The promotion to int happens BEFORE the
    minus operation. Ouch.

    OK, silly code removed (it was only an optimization hint, anyway).

    --
    -----------------------------------------------------------------------------
    | Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
    | (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
    -----------------------------------------------------------------------------
    , Oct 26, 2009
    #6
  7. Re: warning: comparison is always true due to limited range of datatype

    On Oct 27, 9:32 am, -berlin.de (Stefan Ram) wrote:
    > Eric Sosman <> writes:
    > > > if ((unsigned short)-1 < (unsigned short)0) {

    > >
    > > Is the second cast necessary?  (Have I missed something,
    > > yet again?)

    >
    >   Without the second cast, the first operand will be
    >   converted (promoted) to »int«, but since it already
    >   has a positive value, the result should be the same.


    If unsigned short promotes to int, then both sides of <
    will be promoted to int. [If you accept that int 'promotes'
    to int.] If unsigned short promotes to unsigned int, then
    both sides will promote to unsigned int. Both cases are
    irrespective of the second cast since int will promote
    (via usual arithmetic conversions) to usigned int if the
    left operand promotes to unsigned int.

    --
    Peter
    Peter Nilsson, Oct 26, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    2
    Views:
    713
    Randy Howard
    Feb 26, 2005
  2. Fresh
    Replies:
    2
    Views:
    608
    Bo Persson
    Apr 22, 2008
  3. Replies:
    6
    Views:
    333
    Mike Schilling
    Jun 9, 2008
  4. bdb112
    Replies:
    45
    Views:
    1,291
    jazbees
    Apr 29, 2009
  5. Nachy
    Replies:
    11
    Views:
    558
    Kaz Kylheku
    Mar 14, 2012
Loading...

Share This Page