Velocity Reviews > Why, warning: comparison between signed and unsigned integer expressions?

# Why, warning: comparison between signed and unsigned integer expressions?

Ike Naar
Guest
Posts: n/a

 05-31-2012
On 2012-05-31, Lox <(E-Mail Removed)> wrote:
> Sorry, two typos (wrote to fast).
>
> uint32_t x;
> uint8_t y;
>
> x = 255;
> y = x + UINT8_C(1);
>
> y is 256 and not 0 as one would think (if assuming 8 bit
> calculations).

Again, y can only hold values from 0 to 255 inclusive,
so it cannot be 256. How did you come to that conclusion?
Can you show the code?

Here's code that suggests y equals 0:

#include <stdint.h>
#include <assert.h>
int main(void)
{
uint32_t x = 255;
uint8_t y = x + UINT8_C(1);
assert(y == 0);
return 0;
}

> but in:
>
> uint32_t x;
> uint8_t y;
>
> x = 255;
> y = (u8_t)(x + UINT8_C(1));

What is (u8_t) ? Did you mean (uint8_t) ?

> y is 0

Indeed.

Joe Pfeiffer
Guest
Posts: n/a

 05-31-2012
Ike Naar <(E-Mail Removed)> writes:

> On 2012-05-31, Lox <(E-Mail Removed)> wrote:
>> Sorry, two typos (wrote to fast).
>>
>> uint32_t x;
>> uint8_t y;
>>
>> x = 255;
>> y = x + UINT8_C(1);
>>
>> y is 256 and not 0 as one would think (if assuming 8 bit
>> calculations).

>
> Again, y can only hold values from 0 to 255 inclusive,
> so it cannot be 256. How did you come to that conclusion?
> Can you show the code?

If I'm reading the standard correctly, an unsigned char is large
enough to hold values from 0 to 255 (actually "any member of the basic
execution character set"). It doesn't say that it can't be larger than
that.

> Here's code that suggests y equals 0:
>
> #include <stdint.h>
> #include <assert.h>
> int main(void)
> {
> uint32_t x = 255;
> uint8_t y = x + UINT8_C(1);
> assert(y == 0);
> return 0;
> }

I tried a similar experiment, and also got 0 (as you and I both
expected!). I wouldn't be at all surprised to learn that a processor
with a character set that didn't handle 8 bit quantities well, or indeed
some other compiler than gcc even on Intel, was able to store a value
greater than 255 in an unsigned char.

James Kuyper
Guest
Posts: n/a

 05-31-2012
On 05/31/2012 01:09 PM, Joe Pfeiffer wrote:
> Ike Naar <(E-Mail Removed)> writes:
>
>> On 2012-05-31, Lox <(E-Mail Removed)> wrote:
>>> Sorry, two typos (wrote to fast).
>>>
>>> uint32_t x;
>>> uint8_t y;
>>>
>>> x = 255;
>>> y = x + UINT8_C(1);
>>>
>>> y is 256 and not 0 as one would think (if assuming 8 bit
>>> calculations).

>>
>> Again, y can only hold values from 0 to 255 inclusive,
>> so it cannot be 256. How did you come to that conclusion?
>> Can you show the code?

>
> If I'm reading the standard correctly, an unsigned char is large
> enough to hold values from 0 to 255 (actually "any member of the basic
> execution character set"). ...

Actually, the key requirement is that UCHAR_MAX >= 255 (5.2.4.2.1p1).

> ... It doesn't say that it can't be larger than
> that.

While that's all perfectly true, it's not relevant. The type used in
this example was uint8_t, not char. uint8_t is required by the standard
to have exactly 8 values bits, no more, and no less; and no padding bits
(7.20.1.1p2). On any implementation where uint8_t can be implemented,
it's likely (but not required) to be the same type as unsigned char.
However, uint8_t is an optional type, for precisely the reason that it
cannot be implemented as specified on any implementation where CHAR_BIT > 8.

Joe Pfeiffer
Guest
Posts: n/a

 05-31-2012
James Kuyper <(E-Mail Removed)> writes:

> On 05/31/2012 01:09 PM, Joe Pfeiffer wrote:
>> Ike Naar <(E-Mail Removed)> writes:
>>
>>> On 2012-05-31, Lox <(E-Mail Removed)> wrote:
>>>> Sorry, two typos (wrote to fast).
>>>>
>>>> uint32_t x;
>>>> uint8_t y;
>>>>
>>>> x = 255;
>>>> y = x + UINT8_C(1);
>>>>
>>>> y is 256 and not 0 as one would think (if assuming 8 bit
>>>> calculations).
>>>
>>> Again, y can only hold values from 0 to 255 inclusive,
>>> so it cannot be 256. How did you come to that conclusion?
>>> Can you show the code?

>>
>> If I'm reading the standard correctly, an unsigned char is large
>> enough to hold values from 0 to 255 (actually "any member of the basic
>> execution character set"). ...

>
> Actually, the key requirement is that UCHAR_MAX >= 255 (5.2.4.2.1p1).
>
>> ... It doesn't say that it can't be larger than
>> that.

>
> While that's all perfectly true, it's not relevant. The type used in
> this example was uint8_t, not char. uint8_t is required by the standard
> to have exactly 8 values bits, no more, and no less; and no padding bits
> (7.20.1.1p2). On any implementation where uint8_t can be implemented,
> it's likely (but not required) to be the same type as unsigned char.
> However, uint8_t is an optional type, for precisely the reason that it
> cannot be implemented as specified on any implementation where CHAR_BIT > 8.

Ah. I was looking for the string uint8_t in the standard and not
finding it... You are correct.