avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-chat] Type promotion and shift operators


From: Rick Mann
Subject: Re: [avr-chat] Type promotion and shift operators
Date: Wed, 2 Feb 2011 13:28:36 -0800

On Feb 2, 2011, at 12:39:12, Michael Hennebry wrote:

>> 
>> No, I wasn't proposing that as the code I should write. I was trying to 
>> codify what you said. You said, "the type of x<<y is now the type of x after 
>> the usual integer promotions":
> 
> C doesn't believe is doing arithmetic on chars or shorts.
> Had x been a short it would have been promoted to int before the shift.
> In principle, y could be promoted,
> but it wouldn't affect the type of the result.

Well, neither type is char or short. int is 16 bits and signed. I think the the 
literal 1 gets type int. The problem I see is this: according to my K&R C book 
(which you seem to be saying is out of date), the smaller type is promoted to a 
larger type when the types on an operator are different. Which led me to 
believe that the 1 (an implicit int) should be promoted to uint32_t. Now, I'm 
not 100% clear, because they also differ in signdedness.

But you're telling me a "quiet change" (to the language spec, I presume) means 
that for the << operator, the resulting type is the type of the LHS. But you 
also said "after the usual integer promotions," which I took to mean the 
original behavior of C, which is to promote the size of the smaller type to 
something that will fit the larger type.

So, if it first promotes, that means it does the equivalent of

        ((long) 1) << v

But if the result then has the type of the LHS (int), it then casts that result 
to int, thereby throwing away bits. I don't know why they was considered to be 
correct. If I were adding instead of shifting, it would work fine.

So, it seems wrong to me, and it makes for unnecessarily verbose code, as well 
as code that has to be more carefully considered when changing the type of the 
result.

-- 
Rick

> 
>> 1) usual integer promotions (which I take to mean, in this case, the LHS is 
>> promoted to the size of RHS)
>> 2) result of shift operation is type of LHS argument
> 
> Not sure what this means.
> Will hope desired information is provided elsewhere.
> 
>> That seems to say that my original expression:
>> 
>>      foo |= 1 << v;
> 
> The type of 1 << v is the type of 1 which is int.
> At least for v in 0..14, this has well-defined semantics equivalent to
> foo |= (int)(1 << v);
> foo |= 1U << v;
> has well-defined semantics for nonnegative v.
> C doesn't require as much of signed types as it does of unsigned.
> 
>> Behaves as if I had written this:
>> 
>>      foo |= (int) (((long) 1) << v);    // extra parens added for clarity
>> 
>> Which strikes me as terribly wrong.
> 
> It is wrong.
> For v>=15, it definitely would have no well-defined semantics.
> The conversion from signed long to signed int is not value-preserving.
> 
>> When was this change adopted into the language?
> 
> Don't know.
> 
> -- 
> Michael   address@hidden
> "Pessimist: The glass is half empty.
> Optimist:   The glass is half full.
> Engineer:   The glass is twice as big as it needs to be."




reply via email to

[Prev in Thread] Current Thread [Next in Thread]