[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] Bug in shift operation with avr-gcc
From: |
Jan Waclawek |
Subject: |
Re: [avr-gcc-list] Bug in shift operation with avr-gcc |
Date: |
Tue, 7 Jun 2011 20:48:07 +0200 |
>> uint32_t t1;
>> int main(){
>> t1=0xf << (12); // t1 gets fffff000 instead of 0000f000
>> }
>>
>>
>
>uint32_t t1;
>int main(){
> t1=0xfUL << (12); // t1 gets fffff000 instead of 0000f000
>}
>
I'll try to translate :-) :
in avr-gcc, the "int" type is 16 bit (rather than 32 bit, which is the standard
in the PC world nowadays). The C standard states that constants are by default
int (this is not precise, but good enough for our explanation; for more details
go to the standard), i.e. your 0xF is 0x000F, signed. Now if you shift it by 12
to the left, you set (among others) the 15-th bit, which is the sign. So your
right-hand side expression is 0xF000, but it's not 61440 (which it would be if
it would be unsigned int), but it's -4096.
At the moment of assignment to a 32-bit unsigned value, a conversion is
performed, which is in fact a sign extension - again, for the detailed
procedure go to the C standard, and IIRC Derek Jones provides some reasoning
why is it so.
Now what Eric did was that he converted the very first constant explicitly into
unsigned long, which in avr-gcc is equivalent to uint32_t. Since then, the
rules are to perform everything in 32-bit arithmetics, which yields the
expected result straightforwardly.
The keywords for further reading are "integer promotion" and "usual arithmetic
conversions". Enjoy!
Jan Waclawek (The C-hater)