Re: Option to make unsigned->signed conversion always well-defined?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Andrew Haley <aph@xxxxxxxxxx> writes:

> On 10/05/2011 09:11 PM, Ulf Magnusson wrote:
>> Hi,
>>
>> I've been experimenting with different methods for emulating the
>> signed overflow of an 8-bit CPU. The method I've found that seems to
>> generate the most efficient code on both ARM and x86 is
>>
>> bool overflow(unsigned int a, unsigned int b) {
>>     const unsigned int sum = (int8_t)a + (int8_t)b;
>>     return (int8_t)sum != sum;
>> }
>>
>> (The real function would probably be 'inline', of course. Regs are
>> stored in overlong variables, hence 'unsigned int'.)
>>
>> Looking at the spec, it unfortunately seems the behavior of this
>> function is undefined, as it relies on signed int addition wrapping,
>> and that (int8_t)sum truncates bits. Is there some way to make this
>> guaranteed safe with GCC without resorting to inline asm? Locally
>> enabling -fwrap takes care of the addition, but that still leaves the
>> conversion.
>
> inline int8_t as_signed_8 (unsigned int a) {
>   a &= 0xff;
>   return a & 0x80 ? (int)a - 0x100 : a;
> }
>
> int overflow(unsigned int a, unsigned int b) {
>   int sum = as_signed_8(a) + as_signed_8(b);
>   return as_signed_8(sum) != sum;
> }

This version looks good to me.

In general there are two cases: if you have a wider type, and if you do
not.  If you have a wider type, do what Andrew suggests.  If you do not
have a wider type, do the addition using an unsigned type, and see if
the result is smaller than either of the operands.

Ian


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux