bit shifting on an unsigned long

Hi
i was trying to do some bit setting / shifting on a 32 bit integer - unsigned long. So i thought i would test a loop to turn all bits to 0, but it didn't return what i expected. i expected it to continue turning all the 1's to 0's rather than stopping half way and printing 0's for the rest of the loop as it does below. I think i must misunderstand the implication or be using the wrong data type or something. please help.

unsigned long i;

void setup() { 
  Serial.begin(9600);       
}

void loop(){
    i  = 4294967295;
    Serial.println(i, BIN);
 
    for(int f = 0; f < 31; f++){
       i &= ~(1<<f);
       Serial.println(i, BIN); 
    }

    delay(3000);
}

prints through serial

11111111111111111111111111111111

11111111111111111111111111111110

11111111111111111111111111111100

11111111111111111111111111111000

11111111111111111111111111110000

11111111111111111111111111100000

11111111111111111111111111000000

11111111111111111111111110000000

11111111111111111111111100000000

11111111111111111111111000000000

11111111111111111111110000000000

11111111111111111111100000000000

11111111111111111111000000000000

11111111111111111110000000000000

11111111111111111100000000000000

11111111111111111000000000000000

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

Q : why doesn't it continue as expected ?

Q : why doesn't it continue as expected ?

Because the expression ~(1<<f) is a 16-bit integer. If you change it to ~(1UL<<f) it will work.

Mikal

EDIT: Better yet, for the benefit of your code's readers, make i a uint32_t and use ~((uint32_t)1 << f). That way, it's very clear to everyone that you mean to use 32-bit numbers.

Have fun...
M

Thank so much - need to do a bit more reading up on data types / their use / syntax :slight_smile:

ok - i thought i would be able to reach 4294967295 using bit shifting, but my number goes into the negative. I thought if it was unsigned it would always be positive ? i appreciate the 2's complement rule but doesnt that only apply to signed ints' ?
the code

uint32_t  i;

void setup() {
  Serial.begin(9600);
}

void loop(){
    i = 0;
    for(int f = 0; f < 32; f++){
       i |=  (1UL << f);
       Serial.println(i, BIN);
       Serial.println(i, DEC);
    }
   for(int f = 0; f < 32; f++){
       i &= ~(1UL << f);       
       Serial.println(i, BIN);
       Serial.println(i, DEC);
    }
    delay(3000);
}

produces

1

1

11

3

111

7

1111

15

11111

31

111111

63

1111111

127

11111111

255

111111111

511

1111111111

1023

11111111111

2047

111111111111

4095

1111111111111

8191

11111111111111

16383

111111111111111

32767

1111111111111111

65535

11111111111111111

131071

111111111111111111

262143

1111111111111111111

524287

11111111111111111111

1048575

111111111111111111111

2097151

1111111111111111111111

4194303

11111111111111111111111

8388607

111111111111111111111111

16777215

1111111111111111111111111

33554431

11111111111111111111111111

67108863

111111111111111111111111111

134217727

1111111111111111111111111111

268435455

11111111111111111111111111111

536870911

111111111111111111111111111111

1073741823

1111111111111111111111111111111

2147483647

11111111111111111111111111111111

-1

11111111111111111111111111111110

-2

11111111111111111111111111111100

-4

11111111111111111111111111111000

-8

11111111111111111111111111110000

-16

11111111111111111111111111100000

-32

11111111111111111111111111000000

-64

11111111111111111111111110000000

-128

11111111111111111111111100000000

-256

11111111111111111111111000000000

-512

11111111111111111111110000000000

-1024

11111111111111111111100000000000

-2048

11111111111111111111000000000000

-4096

11111111111111111110000000000000

-8192

11111111111111111100000000000000

-16384

11111111111111111000000000000000

-32768

11111111111111110000000000000000

-65536

11111111111111100000000000000000

-131072

11111111111111000000000000000000

-262144

11111111111110000000000000000000

-524288

11111111111100000000000000000000

-1048576

11111111111000000000000000000000

-2097152

11111111110000000000000000000000

-4194304

11111111100000000000000000000000

-8388608

11111111000000000000000000000000

-16777216

11111110000000000000000000000000

-33554432

11111100000000000000000000000000

-67108864

11111000000000000000000000000000

-134217728

11110000000000000000000000000000

-268435456

11100000000000000000000000000000

-536870912

11000000000000000000000000000000

-1073741824

10000000000000000000000000000000

-2147483648

0

0

and never reaches 4294967295 which i thought was the upper limit of an unsigned long / 32 bit number, and i presumed would be represented with 32 1's - can some one please explaing my missunderstanding - thanks

I don't think that "serial.print" knows about "unsigned" numbers.

ah yes - i did some maths and it is still the correct number but the serial port is re-interpreting / printing it differently, all is good, thanks

I don't think that "serial.print" knows about "unsigned" numbers.

Actually it does; it's just that when you specify "DEC", you are requesting the number to be displayed as a signed. If you just call

unsigned long x = 0xFFFFFFFF; // or 0b11111111111111111111111111111111
Serial.println(x);

you should get the expected answer.

Mikal