unsigned char + constant

Discussion in 'C Programming' started by barcaroller, Feb 20, 2010.

  1. barcaroller

    barcaroller Guest

    Does anyone know why the gcc compiler complains about the second 'if'
    condition:


    unsigned char x = 0;
    size_t y = 0;

    // okay; no compiler warning
    if (x < y)
    ...

    // compiler warning: comparing signed and unsigned values
    if ((x+1) < y)
    ...


    My guess is that (x+1) somehow becomes an 'int', but that would not be
    intuitive and could have undesirable consequences.
     
    barcaroller, Feb 20, 2010
    #1
    1. Advertisements

  2. barcaroller

    santosh Guest

    You're basically correct. Quoting a relevant section from the
    standard:

    ----------
    6.3.1.8 (1)

    Otherwise, if the type of the operand with signed integer type can
    represent all of the values of the type of the operand with unsigned
    integer type, then the operand with unsigned integer type is
    converted to the type of the operand with signed integer type.
    ----------

    So (x+1) yields a value of type int since the literal 1 has a higher
    conversion rank than x, on your compiler, which you then compare with
    an unsigned value. This is a standard warning from gcc. You can use
    the switches -Wno-sign-conversion or -Wno-sign-compare to disable
    these specific warnings. Or you can cast one of the objects in the
    expression to get the type of conversions you desire.
     
    santosh, Feb 20, 2010
    #2
    1. Advertisements

  3. barcaroller

    Mark Guest

    Perhaps (x + 1u) would be better.
     
    Mark, Feb 21, 2010
    #3
  4. As does x in the first case.

    Well, actually, it depends on the implementation. If INT_MAX
    can hold the range 0..UCHAR_MAX, then x will be promoted to
    a (signed) int, otherwise it will be promoted to an unsigned
    int for comparison purposes. It may be subject to further
    'arithmetic' conversion depending on size_t.

    I dare say that gcc is checking if the two operands are
    unsigned (prior to integral promotion.) If so, then the
    comparison is fine. If not, then the comparison may or
    may not be fine, hence the warning.
    Intuitive or not, it is what the C language requires.

    However, you can rest assured that any promotion is value
    preserving for non-negative values. That said, x + 1, is
    theoretically problematic and you should check your code
    for errant behaviour on bizarre implementations, should
    you wish the code to be maximally portable.

    If you want the mathematical condition to hold, then the
    second clause can be written portably as...

    if (y != 0 && x < y - 1)

    The original code can fail in the case where y is non-zero
    and x has the value UCHAR_MAX, and x promotes to unsigned
    int. In that case x + 1 will yield 0 (as an unsigned int)
    which of course compares less than a positive value, even
    if y has a positive value lower UCHAR_MAX.
     
    Peter Nilsson, Feb 22, 2010
    #4
  5. barcaroller

    santosh Guest

    I don't clearly remember, but I think you would need the -Wall and
    possibly -Wextra switches to make gcc warn about this.
     
    santosh, Feb 22, 2010
    #5
  6. barcaroller

    Eric Sosman Guest

    (Context: x is unsigned char, y is size_t.)

    There's nothing special about x==UCHAR_MAX that would
    somehow render x+1<y meaningless. On many platforms (including
    the one the O.P. uses), x+1 would just be 256, a perfectly
    good int, which would then be converted to size_t and compared
    to y.

    It's of course possible that the meaning of the expression
    is not what the O.P. intended -- but that's true of any construct,
    even printf("Hello, world!\n").
     
    Eric Sosman, Feb 22, 2010
    #6
  7. Except for the pathological case where INT_MAX == UCHAR_MAX.

    Also, if UCHAR_MAX == UINT_MAX then x + 1 yields 0 and compares
    less than _any_ non zero y. Of course, that case isn't meanless
    per se, but it's unlikely to be the intended effect of the
    condition.
     
    Peter Nilsson, Feb 22, 2010
    #7
  8. Why is that bad? In any case, it's not the pathological case.
    On such implementations INT_MAX < UCHAR_MAX.
     
    Peter Nilsson, Feb 22, 2010
    #8
  9. Peter, thanks for your beautiful explanation. But I have some doubt. I
    think Op's code doesn't fail. OP's code will fail when x types of
    unsigned int and y types of long. Integral expression defaults to int,
    so x+1 with x equals to UCHAR_MAX won't yields 0, but value of
    UCHAR_MAX+1 types of int.
     
    lovecreatesbeauty, Feb 23, 2010
    #9
  10. barcaroller

    Eric Sosman Guest

    ... implying at least fourteen padding bits in an int, which
    as far as I know only happens on the DeathStation, and only for
    programs compiled in the dark of the Moon.
    This situation seems a good deal more likely. DSP's where
    sizeof(int)==1 have been mentioned elsethread.
     
    Eric Sosman, Feb 23, 2010
    #10
  11. barcaroller

    Richard Bos Guest

    Not allowed. 6.2.5#8 in C99:

    # 8 For any two integer types with the same signedness and different
    # integer conversion rank (see 6.3.1.1), the range of values of the
    # type with smaller integer conversion rank is a subrange of the
    # values of the other type.

    (And yes, 6.3.1.1 does say that "the rank of int ... shall be greater
    than ... the rank of signed char".)

    In C89, it's even simpler; in 6.1.2.5, it says:

    # There are four signed integer types, designated as signed char,
    # short int, int, and long int.
    # ...
    # In the list of signed integer types above, the range of values of each
    # type is a subrange of the values of the next type in the list.

    Richard
     
    Richard Bos, Feb 23, 2010
    #11
  12. Yes it is.
    ^^^^^^^^^^^^^^^
    There are many implementations today where INT_MAX < USHRT_MAX.
     
    Peter Nilsson, Feb 23, 2010
    #12
  13. No, promotion to unsigned int is possible if int cannot
    represent the values of an expression.
    It can if INT_MAX < UCHAR_MAX, e.g. embedded systems
    (freestanding implementations) where integer types
    are all the same size, say 32 or 64-bit.
    On most hosted implementations, yes.
     
    Peter Nilsson, Feb 23, 2010
    #13
  14. barcaroller

    Richard Bos Guest

    *Slaps own head*

    Richard
     
    Richard Bos, Mar 1, 2010
    #14
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.