This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]