[SOLVED] Bitshift on uint32_t problem

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello

 

I'm using the following code to print individual bits of an uint32_t variable

uint32_t test = 0b11111111111111111111111111111111;
uint8_t size = sizeof(test) << 3; // multiply by 8
uint8_t bit = 0;

for (uint8_t i = 0; i < size; i++)
{
    // compute bit
    bit = (test & (1 << i)) ? 1 : 0;
    usartSend("%d - %d\n\r", i, bit);

    // do stuff with the bit
}

The problem is that the 16 most significant bits are printed out as 0, so the result of the above code is

0 - 1
.
.
.
15 - 1
16 - 0
.
.
.
31 - 0

The same happens if the uint32 is a random number and not just all 1's.

 

I verified that the variable is actually 4 bytes by printing its sizeof(), and also verified that it matches UINT32_MAX, so the variable is stored correctly in memory.

 

I confirmed that the code works for 8 and 16 uint variables, the problem occurs exactly after two bytes, so this must be some ignorance of mine regarding the hw architecture, what is it?

 

Thanks

Last Edited: Wed. Jun 22, 2022 - 11:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thiird wrote:

    bit = (test & (1 << i)) ? 1 : 0;

fyi, a linter generates a 'shift of signed' message.

    bit = (test & ((uint8_t)1 << i)) ? 1 : 0;

 


PC-lint Plus Online Demo - Gimpel Software - The Leader in Static Analysis for C and C++ with PC-lint Plus

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Damn, I had read about casting the 1 to whatever type you are using earlier but had forgotten to do it, thanks!

Final code

bit = (test & ((uint32_t)1 << i)) ? 1 : 0;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This should fix it:

Also your printing the bits backwards which makes inspection difficult. I reversed the order.

uint32_t test = 0b11111111111111111111111111111111;
uint8_t size = sizeof(test) << 3; // multiply by 8
uint8_t bit = 0;

for (uint8_t i = size; i--;)
{
    // compute bit
    bit = (test & (1UL << i)) ? 1 : 0;
    usartSend("%d - %d\n\r", i, bit);
    
    // do stuff with the bit
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW ltoa() with radix 2 might be a quicker/easier way to accomplish all this ;-)

 

(true, it does not pad leading 0's though)

Last Edited: Wed. Jun 22, 2022 - 11:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Yes confirmed working, thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you don't have a barrel shifter, you can make it a bit faster:

 

uint32_t test = 0b11111111111111111111111111111111;
uint8_t size = sizeof(test) << 3; // multiply by 8
uint8_t bit;
uint32_t mask = 1u;

for (uint8_t i = 0u; i < size; i++)
{
    // compute bit
    bit = (test & mask) ? 1 : 0;
    mask <<= 1; 
    usartSend("%d - %d\n\r", i, bit);

    // do stuff with the bit
}

or if the original value of test is not needed anymore: 

uint32_t test = 0b11111111111111111111111111111111;
uint8_t size = sizeof(test) << 3; // multiply by 8
uint8_t bit;

for (uint8_t i = 0u; i < size; i++)
{
    // compute bit
    bit = (test & 1u) ? 1 : 0;
    test >>= 1;
    usartSend("%d - %d\n\r", i, bit);

    // do stuff with the bit
}