Hi,

I'm not subscribed, so if you want to reach me directly you have to send an email directly to me; otherwise I'll pick up any answer via the web-archives.

I'm a little bit confused w.r.t. to signed/unsigned multiplication on x86_64:

Assume multiplying (signed <some integer type)-1 by (unsigned <same integer type)20 and cast that value to a larger integer. With gcc-3.4.3 (pretty sure head CVS is the same):

1.
(signed long) = (signed int) = (signed short) = (signed char) x (unsigned char)

This yields proper (?) sign extension to every integer type. In hex notation:

a = -1 * 20, then a = 0xffff ffff ffff ffec

2.
(signed long) = (signed int) = (signed short) x (unsigned short)

Dito.

a = -1 * 20, then a = 0xffff ffff ffff ffec

3.
(signed long) = (signed int) x (unsigned int)

Surprisingly the sign is not promoted in this case:

a = -1 * 20, then a = 0x0000 0000 ffff ffec


IMHO, this is a bug. Below is a short test program which tries to execute the three scenarios.

Regards

Claus

############################ snip ####################################
#include <stdio.h>

short char_mix(signed char sign, unsigned char val)
{
        return sign * val;
}

int short_mix(signed short sign, unsigned short val)
{
        return sign * val;
}

long int int_mix(int sign, unsigned int val)
{
        return sign * val;
}

int main(int argc, const char *argv[])
{
        short    short_res;
        int      int_res;
        long int long_int_res;

        short_res     = char_mix(-1, 20);
        int_res      = short_mix(-1, 20);
        long_int_res = int_mix(-1, 20);

        printf("Char : 0x%016lx | 0x%08x | 0x%04x\n",
               (unsigned long)short_res, (unsigned int)short_res, (unsigned 
short)short_res);
        printf("Short: 0x%016lx | 0x%08x\n",
               (unsigned long)int_res, (unsigned int)int_res);
        printf("Int  : 0x%016lx\n", (unsigned long)long_int_res);
}
############################ snap ####################################

Reply via email to