Integral conversions in C/C++
Tom St Denis
tstdenis@ellipticsemi.com
Sun Apr 20 18:27:00 GMT 2008
On Sun 20/04/08 11:55 AM , Christian Böhme monodhs@gmx.de 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
More information about the Gcc-help
mailing list