On Sun 20/04/08 11:55 AM , Christian Böhme monodhs@xxxxxx sent: > Tom St Denis wrote: > > > What type is the expression -(b * 2u)? > > It _should_ be that of the destination type of the whole expression. > > and thus integral conversion of an rvalue applied. But it isn't. The process works like this, you end up with 2^32 - 16, which is a positive unsigned number. This then gets zero extended (since it's unsigned) and stored in a 64-bit integer. How is what you wrote any different from a = 4294967280UL; > 2^32 - 16 is not what -(b * 2u) expresses. The result of x = b * 2u Numerically, that's what it does. you took 8, doubled it, then negated it as a 32-bit two's complement. Then you took that unsigned expression and stored it in a 64-bit type. So effectively, you are doing a = 4294967280UL; I ask again. Why would that be sign extended? You're right that a conversion is applied before being stored, but the conversion rule applies to the = operator, nothing else. So you have an expression who's result is converted to a signed 64-bit int. And the rule states that from a 32-bit unsigned value that it will be zero extended. Otherwise, the above statement ends with -16 in a which is not what you're doing. > > Why does this work when your example does not? > > For once, it does not give exact sizes for the objects in use. > > Secondly, the type cast is acually redundant to the original version. > > Finally, the example may work for b = 8 but not for b = 0xffffffff > > and hence is _wrong_ with b being a _variable_ whose value no > > compiler can ever predict an therefore _should_ use a temporary > > with an appropriate type which, again, is the point of the > > whole discussion. > I have no idea what you're talking about. b = 0xFFFFFFFF * 2 would get you 0xFFFFFFFE which btw is congruent to -2 mod 2^32. However, if you do long long a = 0xFFFFFFFEUL; a == -2 will be false, since it's not sign extended. Using your logic ... float a = 3; int b; b = a / 1.5; What is the value that should be in b? Well if we convert first we get b = 3 / 1 [or 2] so b is either 3 or 1. How is that advantageous? Instead, what ACTUALLY happens is the division occurs first, resulting in a float of 2, then that is converted before being stored in b. I suggest you read either the C standard or at least the K&R C book and learn about conversion rules, variable promotions, etc... In short, if you want signed arithmetic and expressions, use signed variables [or cast them to a signed type]. Negating an unsigned variable or expression is not usually a good idea [or particularly useful]. This is also totally off-topic for this list, as you're not discussing a GCC bug. Tom