[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)

reply via email to

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