Shifting a mask to read bits - but it doesn't like longs!

Hello!

I have a long that I want to read a bit of at a time. I use a mask shifted across it to do so. This works great for a while then goes berserk - at bit 16, the mask suddenly fills with 1, and then disappears completely:

T_FC  Masking through "DEADBEEF" ( 11011110101011011011111011101111 )

T_FC:  sending bit  0, which is 1. Mask was 1
T_FC:  sending bit  1, which is 1. Mask was 10
T_FC:  sending bit  2, which is 1. Mask was 100
T_FC:  sending bit  3, which is 1. Mask was 1000
T_FC:  sending bit  4, which is 0. Mask was 10000
T_FC:  sending bit  5, which is 1. Mask was 100000
T_FC:  sending bit  6, which is 1. Mask was 1000000
T_FC:  sending bit  7, which is 1. Mask was 10000000
T_FC:  sending bit  8, which is 0. Mask was 100000000
T_FC:  sending bit  9, which is 1. Mask was 1000000000
T_FC:  sending bit 10, which is 1. Mask was 10000000000
T_FC:  sending bit 11, which is 1. Mask was 100000000000
T_FC:  sending bit 12, which is 1. Mask was 1000000000000
T_FC:  sending bit 13, which is 1. Mask was 10000000000000
T_FC:  sending bit 14, which is 0. Mask was 100000000000000
T_FC:  sending bit 15, which is 1. Mask was 11111111111111111000000000000000
T_FC:  sending bit 16, which is 0. Mask was 0. 
T_FC:  sending bit 17, which is 0. Mask was 0. 
T_FC:  sending bit 18, which is 0. Mask was 0. 
T_FC:  sending bit 19, which is 0. Mask was 0. 
T_FC:  sending bit 20, which is 0. Mask was 0. 
T_FC:  sending bit 21, which is 0. Mask was 0. 
T_FC:  sending bit 22, which is 0. Mask was 0. 
T_FC:  sending bit 23, which is 0. Mask was 0. 
T_FC:  sending bit 24, which is 0. Mask was 0.

To me, that looks like the mask has overflown, but the mask - like the sequence which appears to be represented fine - is a long (4 bytes / 32 bits). It seems that on my uC (an ATmega16U4 on an Arduino Micro), longs are 4 bytes, so this seems unlikely to be in. I think I misunderstand something about the way longs are stored, but I can't find anything. I'm using unsigned longs, although for bit operations like this I presume it makes no difference if I used unsigned or not.

Relevant code:

unsigned long sequence = 0xDEADBEEFL; // 4 byte max.

unsigned long mask = 0L;

int bitposition = 0;
bool outbit = 0;
...

unsigned int fclength = sizeof(sequence) * 8; // want in bits!
bitposition = 0;

...

 while (bitposition < fclength)
  {
    mask = (1 << bitposition);
    outbit = (sequence & mask);

    Serial.print("T_FC:  sending bit ");     
    Serial.print(bitposition, DEC);     
    Serial.print(", which is ");  
    Serial.print(outbit, BIN); 
    Serial.print(". Mask was ");   
    Serial.print(mask, BIN); 
    Serial.print(". \n\r");     
   ...
    bitposition++; 
   }

Any thoughts? Thanks!

    mask = (1 << bitposition);

You are shifting a 16-bit signed int there. Try this instead:

    mask = (1UL << bitposition);

Yes, that did it! Thank you.

I understand this happens because the expression in the brackets is evaluated to a 16-bit int, since one of the operands (the "1") is 16-bit, right? And this is truncated and all messed up?

alexandicity:
I understand this happens because the expression in the brackets is evaluated to a 16-bit int, since one of the operands (the "1") is 16-bit, right?

Yup. Google "C++ promotions", if you have a mind to.