John Matthews wrote:
> --- In c-prog@yahoogroups.com, "Pedro Izecksohn" <[EMAIL PROTECTED]> wrote:
>> OK, I wrote a bad piece of code. Let me try to codify my problem again:
>>
>> #include <limits.h>
>> #include <stdio.h>
>>
>> int main (void) {
>> unsigned short int a;
>> unsigned long long int b, c;
>> a = USHRT_MAX;
>> b = (a*a);
>> c = ((unsigned int)a*(unsigned int)a);
>> printf ("Why %llx != %llx ?\n", b, c);
>> return 0;
>> }
>>
>> When I execute it I get:
>> Why fffffffffffe0001 != fffe0001 ?
>>
>> b is wrong.
> 
> I see what you are saying - ignoring what C says should happen, and
> assuming USHRT_MAX = 0xffff, you have:
> 
> b = a * a
>   = 0xffff * 0xffff
>   = 0xfffe0001
> 
> So why do you get 0xfffffffffffe0001?
> 
> Good question - my guess is that at some point the result is a
> negative (ie. signed) value, and this gets sign-extended.
> 
> For example, if you have -1 as a signed short, and want to convert it
> to a signed int, the result should still be -1. But if you like at
> these values in hex, you have 0xffff (short) becoming 0xffffffff
> (int), which looks similar to what has happened to b in your program.
> 
> But hopefully some can quote the relevant bit of the Standard.
> 
> John

Wow.  I totally missed that.  All this time I was thinking the OP was 
complaining about something involving 'c' instead of 'b'.

Without typecasting, _operators_ tend to behave "oddly" when differing 
data types are involved.  At least they don't behave like you would 
think they should.  There are a set of rules regarding these things in 
the Standard, but I've just found it MUCH easier to use typecasting to 
the types I want and then force a final typecast at the end of the 
procedure instead of trying to memorize the rules.

b = (unsigned long long int)(((unsigned int)a) * ((unsigned int)a));

Ugly, but effective.  Although, I would personally do something more 
along the lines of:

b = (UInt64)(((UInt32)a) * ((UInt32)a));

(I'm pretty sure the rule is something like operators automatically 
convert from unsigned to signed unless there is a typecast involved on 
one of the operands, but don't quote me on that as I haven't ever tried 
to figure this out.  My solution is to ALWAYS go overkill on typecasting 
in this situation to make 100% certain that the compiler will do EXACTLY 
what I want it to do.  My approach has never failed me but it does use a 
lot of parenthesis.)

-- 
Thomas Hruska
CubicleSoft President
Ph: 517-803-4197

*NEW* MyTaskFocus 1.1
Get on task.  Stay on task.

http://www.CubicleSoft.com/MyTaskFocus/

Reply via email to