 # Bitwise operations on 32 bit integers

Hi,

Is there a limitation on 32 bit operations using bitwise operators?

Can anyone please explain the change in output for i =15, why the x value changes so much for i =15 condition?

``````void setup() {
Serial.begin(115200);
}

void loop() {
for (int i = 0; i < 16; i++)
{
uint32_t x = 0;
x = (uint32_t)(1 << (uint32_t)i);
Serial.print("x is : ");
Serial.println(x, BIN);
}
}
``````

use '1UL' in place on '1'

1 Like

That is an easy to make mistake.
The number 1 defaults to a integer type 'int', which is a 16-bit signed integer for the basic Arduino boards. You should shift a 32-bit value and not just a integer 'int'.

This is my solution, I shift a 'UL' (unsigned long) number:

``````void setup()
{
Serial.begin(115200);

for (int i = 0; i < 16; i++)
{
uint32_t x = 1UL << i;
Serial.print("x is : ");
Serial.println(x, BIN);
}
}

void loop() {}
``````

In Wokwi:

[EDIT] Changed occording to @TheMemberFormerlyKnownAsAWOL in Reply 6

1 Like

By default, calculations are done with 16-bit integers (on an 8-bit microcontroller). At the moment that you shift the integer 1 15 times, the results is 1000 0000 which is a negative number.

You need to force the compiler to use an unsigned 32 bit number by using 1UL. Below a slightly modified version of your code

``````void setup() {
Serial.begin(115200);
}

void loop() {
for (int i = 0; i < 16; i++)
{
Serial.println(i);
uint32_t x = 0;
x = (uint32_t)(1UL << (uint32_t)i);
Serial.print("x is : ");
Serial.println(x, BIN);
}
delay(500);
}
``````

Note:
Your original casts are not needed, ` x = 1UL << i;` works as well.

1 Like

Thanks to all for explaining.
I understood it now.

sp. "The number 1 defaults to an int . You should shift a 32-bit integer type (e.g. uint32_t), and not just an int."

2 Likes

The width of the data shifted is set by the left hand value, not the righthand value (which never needs to be more than a byte anyway)

So use
`1ul << i`

Another way:

``````    uint32_t x = 1;
x = x << i;
``````
1 Like

And sure that we can do it with a one-liner I can only think of 'uint32_t x = 1ul << i;'

This is one case where the "the usual conversions" are not done. If you were using +, -, * or many other dyadic operators, the fact that one operand was 'uint32_t' would convert the other side from 'int' to 'uint32_t'. But not shifting.

I, too, found that out the hard way. 1 Like

Interesting...

Nothing wrong with that (I think).