Bitmasking and shifting

I have a simple problem and have no doubt that the solution is simple but I can't see the wood for the trees in this sketch

void setup()
{
  Serial.begin(115200);
  for (uint8_t x = 0; x < 20; x++)
  {
    uint32_t test = 1UL << x;
    Serial.print("bit position : ");
    Serial.print(x);
    Serial.print("\t");
    printFullBin(test);
  }
}

void loop()
{
}

void printFullBin(uint32_t value)
{
  for (int bit = (sizeof(value) * 8) - 1; bit >= 0; bit--)
  {
    uint32_t mask = value & (1 << bit);
    if (mask & value)
    {
      Serial.print(1);
    }
    else
    {
      Serial.print(0);
    }
  }
  Serial.println();
}

Its purpose is to print the value of a bit in an unsigned long variable with a view to testing the value and taking action based upon it

The output from the sketch is

bit position : 0	00000000000000000000000000000001
bit position : 1	00000000000000000000000000000010
bit position : 2	00000000000000000000000000000100
bit position : 3	00000000000000000000000000001000
bit position : 4	00000000000000000000000000010000
bit position : 5	00000000000000000000000000100000
bit position : 6	00000000000000000000000001000000
bit position : 7	00000000000000000000000010000000
bit position : 8	00000000000000000000000100000000
bit position : 9	00000000000000000000001000000000
bit position : 10	00000000000000000000010000000000
bit position : 11	00000000000000000000100000000000
bit position : 12	00000000000000000001000000000000
bit position : 13	00000000000000000010000000000000
bit position : 14	00000000000000000100000000000000
bit position : 15	00000000000000001000000000000000
bit position : 16	00000000000000001000000000000000
bit position : 17	00000000000000001000000000000000
bit position : 18	00000000000000001000000000000000
bit position : 19	00000000000000001000000000000000

All goes well until we reach bit 16 and I can't or the life of me see what I have done wrong. Perhaps a fresh set of eyes will spot the problem and point out what is probably blindingly obvious

The type of the literal 1 is int, so on an AVR with 16-bit integers, you cannot shift it more than 16 bits. Try this:

uint32_t mask = uint32_t(1) << bit;

Also, you're doing the bitwise and with value twice.

Or try

uint32_t maskedValue = value & (1ul << bit);
If (maskedValue) …

Using bitread would do the job too, it’s defined like this

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

So the shifting is applied to the value and you only check the LSb
So it works with various byte length

Thanks guys

Problem solved

Hi @UKHeliBob

So that we can learn, what was the solution?

RV mineirin

Problem solved by explicitly making the 1 into an unsigned long

1 Like

TKS.

A bit less typing...
uint32_t mask = 1ul << bit;

Yep, as suggested also in #3

I think right shifting and masking with 1 is better as you always get a consistant 0 or 1 as an answer and it works with all integral types regardless of architectural dependencies.

1 Like