This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Integral conversions in C/C++
Christian BÃhme wrote:
> Andrew Haley wrote:
>
>> ISO/IEC 14882:1998(E)
>> 5 Expressions
>>
>> 9
>
> That's _chapter_ 5 [expr], para 9 over here.
>
>>> vs. 4.7 "Integral conversions" as in the subject of the OP.
>>
>> Right, and you have now had the exact language quoted to you.
>
> Which, surprise, makes no mention of integral conversions nor
> references to section 4.7 [conv.integral]. There, para 7 deserves
> special attention:
>
> "The conversions allowed as integral promotions are excluded from
> the set of integral conversions."
>
> That was the whole point of the OP (Did you read the subject ?).
Unfortunately I did. yes.
> But back to the original example:
>
>> Your first example was
>>
>> int64_t a;
>> uint32_t b = 8;
>>
>> a = -(b * 2u);
>>
>> So, the last section of Para 9 applies: b is promoted to unsigned
>> int,
>
> According to the OP b is of type uint32_t which coincidentally in
> this particular example on a 32 bit machine, is a typedef from
> unsigned int.
OK.
> Contrary to what the specifier may suggest, we all
> know that ``typedef'' actually only introduces another name or
> _alias_ for the name of the type that is given in a typedef
> declaration. The literal constant 2u is, again, of type unsigned
> int. According to 5.6 [expr.mul], (b * 2u) then yields a result
> that is of type unsigned int. Where was there integral promotion
> applied again ?
The operands, and the result, are all of type unsigned int, which
presumably is 32 bits in this case.
>> int64_t a;
>> uint32_t b = 8;
>>
>> a = -((int64_t )(b * 2u));
>>
>> the unsigned int result of (b * 2u) is converted to int64_t and
>> that is negated.
>
> As already stated elsewhere, this only _happens_ to be the correct
> result. If b = 0xffffffff, then the above version yields the
> negated value of (b * 2u), the latter being not closed over
> the set that uint32_t represents producing a modulo 2^32 result.
So what? The compiler does what the standard says it must.
> If, as already assumed elsewhere, the 32 bit machine in question
> provided a 32 unsigned integer multiplication that produces a 64
> bit unsigned integer result, the compiler will _never_ emit code
> using this instruction based on information withheld by a standard
> conforming frontend that the type of the result _must_ be that
> of the operands and precluding the conversion to a type large
> enough such that the multiplication is closed.
Right: the compiler can use such an instruction, but it must discard
the upper part of the result.
> A 64 bit unsigned
> int can then be negated yielding a _negative_ number as the correct
> result.
"The correct result"? The correct result is whatever the standard
says it is.
> The latter can be enforced by a statement like
>
> a = -(((uint64_t )b) * 2u);
>
> which, however, requests a 64 bit unsigned integer multiplication
> which may be non existent or abysmally slow on the target. This
> is the problem that _can_ precisely be avoided by integral conversion
> applied during the multiplication operation.
Right, so it sounds as though you do understand the standard. What,
then, is your point?
Andrew.