Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

unsigned char + constant

2 views
Skip to first unread message

barcaroller

unread,
Feb 20, 2010, 12:10:47 PM2/20/10
to

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.

santosh

unread,
Feb 20, 2010, 12:27:00 PM2/20/10
to
barcaroller <barca...@music.net> writes:

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.


Mark

unread,
Feb 21, 2010, 6:56:51 PM2/21/10
to
santosh wrote:

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

[snip]


> 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.

Perhaps (x + 1u) would be better.

--
Mark

Branimir Maksimovic

unread,
Feb 21, 2010, 7:05:18 PM2/21/10
to
Well actually, I would leave this warning, as maintainers would notice
that and correct possible bug, as x+1<y is meaningless when
x == UCHAR_MAX, anyway.
x+1<=UCHAR_MAX would be completely different thing.

Greets

Peter Nilsson

unread,
Feb 21, 2010, 7:42:06 PM2/21/10
to
"barcaroller" <barcarol...@music.net> wrote:
> 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',

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.

> but that would not be intuitive and could have undesirable
> consequences.

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

pete

unread,
Feb 21, 2010, 9:19:17 PM2/21/10
to

Given:


unsigned char x = 0;
size_t y = 0;

Then:
if (x + 1u < y)
has neither a warning to be read,
nor a bug to be fixed.

--
pete

Branimir Maksimovic

unread,
Feb 21, 2010, 9:43:48 PM2/21/10
to
pete wrote:
>
> Given:
> unsigned char x = 0;
> size_t y = 0;
> Then:
> if (x + 1u < y)
> has neither a warning to be read,
> nor a bug to be fixed.
>
Well OP wasn't specific. Which version of gcc (and platform), with
complete source code that gives warning.
I've tried gcc 4.4 (and comeau online), but cannot reproduce warning.

Greets

santosh

unread,
Feb 22, 2010, 2:46:22 AM2/22/10
to
Branimir Maksimovic <bm...@hotmail.com> writes:

I don't clearly remember, but I think you would need the -Wall and
possibly -Wextra switches to make gcc warn about this.


Branimir Maksimovic

unread,
Feb 22, 2010, 2:49:08 AM2/22/10
to
santosh wrote:
>
> I don't clearly remember, but I think you would need the -Wall and
> possibly -Wextra switches to make gcc warn about this.
>
>

-Wextra did the trick ;)

Greets

Eric Sosman

unread,
Feb 22, 2010, 9:36:29 AM2/22/10
to

(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
eso...@ieee-dot-org.invalid

Peter Nilsson

unread,
Feb 22, 2010, 4:21:32 PM2/22/10
to
Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> On 2/21/2010 7:05 PM, Branimir Maksimovic wrote:
> > Mark wrote:
> > > Perhaps (x + 1u) would be better.
> >
> > Well actually, I would leave this warning, as maintainers
> > would notice that and correct possible bug, as x+1<y is
> > meaningless when x == UCHAR_MAX, anyway.
> > x+1<=UCHAR_MAX would be completely different thing.
>
>      (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.

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

Branimir Maksimovic

unread,
Feb 22, 2010, 4:29:20 PM2/22/10
to
Peter Nilsson wrote:
> Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> On 2/21/2010 7:05 PM, Branimir Maksimovic wrote:
>>> Mark wrote:
>>>> Perhaps (x + 1u) would be better.
>>> Well actually, I would leave this warning, as maintainers
>>> would notice that and correct possible bug, as x+1<y is
>>> meaningless when x == UCHAR_MAX, anyway.
>>> x+1<=UCHAR_MAX would be completely different thing.
>> (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.
>
> Except for the pathological case where INT_MAX == UCHAR_MAX.
>

Well it's not pathological case, because I remember someone of regulars
here mentioned that some DSPs have bad habit that all types are
32 bits...

Greets

christian.bau

unread,
Feb 22, 2010, 4:50:13 PM2/22/10
to

My impression is that gcc can give rather annoying warnings. The
warnings for "struct so_and_so x = { 0 };" are one thing, warnings for
comparison between signed and unsigned values _where it is obvious to
anyone with an ounce of brain that the result is what is intended_ are
another thing.

Say you have

int i;
for (i = 0; i < sizeof (char *); ++i) { /* dosomething */ }

and you get a warning because you dared to compare a signed and an
unsigned integer. But quite clearly the unsigned number is a small
integer, the integer i is always positive, and as a result the code
will always do what the developer intended.

christian.bau

unread,
Feb 22, 2010, 4:52:09 PM2/22/10
to
On Feb 22, 9:29 pm, Branimir Maksimovic <bm...@hotmail.com> wrote:

> Well it's not pathological case, because I remember someone of regulars
> here mentioned that some DSPs have bad habit that all types are
> 32 bits...

On those processors both operands in the comparison will be unsigned.
You get plain straightforward unsigned integer arithmetic. If this
statement gets a warning, then there is about nothing at all that
wouldn't.

christian.bau

unread,
Feb 22, 2010, 4:52:25 PM2/22/10
to
On Feb 22, 2:36 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:

My impression is that gcc can give rather annoying warnings. The

Peter Nilsson

unread,
Feb 22, 2010, 5:25:02 PM2/22/10
to
Branimir Maksimovic <bm...@hotmail.com> wrote:

> Peter Nilsson wrote:
> > Except for the pathological case where INT_MAX == UCHAR_MAX.
>
> Well it's not pathological case, because I remember someone of
> regulars here mentioned that some DSPs have bad habit that all
> types are 32 bits...

Why is that bad? In any case, it's not the pathological case.
On such implementations INT_MAX < UCHAR_MAX.

--
Peter

Branimir Maksimovic

unread,
Feb 22, 2010, 5:41:58 PM2/22/10
to

It's not bad, just it happens that usually people think that byte is
always 8 bits. and that char == byte.
in French (octet as I remember)

Greets

lovecrea...@gmail.com

unread,
Feb 23, 2010, 4:53:50 AM2/23/10
to

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.

Eric Sosman

unread,
Feb 23, 2010, 3:05:24 PM2/23/10
to
On 2/22/2010 4:21 PM, Peter Nilsson wrote:
> Eric Sosman<esos...@ieee-dot-org.invalid> wrote:
>> On 2/21/2010 7:05 PM, Branimir Maksimovic wrote:
>>> Mark wrote:
>>>> Perhaps (x + 1u) would be better.
>>>
>>> Well actually, I would leave this warning, as maintainers
>>> would notice that and correct possible bug, as x+1<y is
>>> meaningless when x == UCHAR_MAX, anyway.
>>> x+1<=UCHAR_MAX would be completely different thing.
>>
>> (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.
>
> Except for the pathological case where INT_MAX == UCHAR_MAX.

... 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.

> 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.

This situation seems a good deal more likely. DSP's where
sizeof(int)==1 have been mentioned elsethread.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Richard Bos

unread,
Feb 23, 2010, 4:20:39 PM2/23/10
to
Peter Nilsson <ai...@acay.com.au> wrote:

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

Peter Nilsson

unread,
Feb 23, 2010, 5:31:12 PM2/23/10
to
On Feb 24, 8:20 am, ralt...@xs4all.nl (Richard Bos) wrote:

> Peter Nilsson <ai...@acay.com.au> wrote:
> > On such implementations INT_MAX < UCHAR_MAX.
>
> Not allowed. 6.2.5#8 in C99:

Yes it is.

> # 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.

There are many implementations today where INT_MAX < USHRT_MAX.

--
Peter

Peter Nilsson

unread,
Feb 23, 2010, 5:36:46 PM2/23/10
to
"lovecreatesbea...@gmail.c0m" <lovecreatesbea...@gmail.com> wrote:
> Peter Nilsson <ai...@acay.com.au> wrote:
> > "barcaroller" <barcarol...@music.net> wrote:
> > > ...
> > >     if ((x+1) < y)
> > ...

> > 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.
>
> ...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,

No, promotion to unsigned int is possible if int cannot
represent the values of an expression.

> so x+1 with x equals to UCHAR_MAX won't yields 0,

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.

> but value of UCHAR_MAX+1 types of int.

On most hosted implementations, yes.

--
Peter

Richard Bos

unread,
Mar 1, 2010, 4:15:35 PM3/1/10
to
Peter Nilsson <ai...@acay.com.au> wrote:

> On Feb 24, 8:20=A0am, ralt...@xs4all.nl (Richard Bos) wrote:
> > Peter Nilsson <ai...@acay.com.au> wrote:
> > > On such implementations INT_MAX < UCHAR_MAX.
> >
> > Not allowed. 6.2.5#8 in C99:
>
> Yes it is.
>
> > # 8 For any two integer types with the same signedness and
> ^^^^^^^^^^^^^^^

*Slaps own head*

Richard

0 new messages