[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-chat] Type promotion and shift operators
From: |
Michael Hennebry |
Subject: |
Re: [avr-chat] Type promotion and shift operators |
Date: |
Wed, 2 Feb 2011 14:39:12 -0600 (CST) |
User-agent: |
Alpine 1.00 (DEB 882 2007-12-20) |
On Wed, 2 Feb 2011, Rick Mann wrote:
On Feb 2, 2011, at 10:49:11, Michael Hennebry wrote:
On Wed, 2 Feb 2011, Rick Mann wrote:
On Feb 2, 2011, at 08:15:40, Michael Hennebry wrote:
On Wed, 2 Feb 2011, Rick Mann wrote:
I was working with some uint32_t variables, using shifts, like this:
uint32_t foo = 0;
for (...)
{
uint32_t v = // some value between [0, 31)
foo |= 1 << v;
^
The type of RHS is int regardless of the type of v.
}
This didn't work correctly for values of v greater than 15 until I changed the
line to:
foo |= 1UL << v;
^^^
The type of RHS is unsigned long regardless of the type of v.
From what I understand of C, it should've promoted 1 to long, but maybe it's a
signed-vs-unsigned issue? What's happening on an ATmega644A with this code?
'Twas a quiet change.
the type of x<<y is now the type of x after the usual integer promotions.
So, it looks like this?
foo = (int) ((long) 1 << v)
If foo is still uint32_t, don't coerce to int.
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.
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."
- [avr-chat] Type promotion and shift operators, Rick Mann, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, Michael Hennebry, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, Rick Mann, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, Michael Hennebry, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, Rick Mann, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators,
Michael Hennebry <=
- Re: [avr-chat] Type promotion and shift operators, Rick Mann, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, David A. Lyons, 2011/02/02
- Re: [avr-chat] Type promotion and shift operators, Michael Hennebry, 2011/02/02