Bitwise operations - very unexpected results on Arduino.

Why does this code have a different result when I run it on my Arduino, then when I run it on my PC?

Serial.println((0<<24 | 18<<16 | 176<<8 | 83));

Expected result (on my PC): 1224787
Unexpected result (on my Arduino): -20397

I tried everything I could think of including casing every single value to unsigned integers, casting the result to an unsigned integer, using variables and many more things that I already forgot… but nothing worked.

So my questions are:
Why is this happening?
How can I get my expected result on an Arduino?

cast them to uint32_t.

Holy cow, it works! Thank you so much. :slight_smile:
May I ask what uint32_t is internally?

May I ask what uint32_t is internally?

It is a 32 bit unsigned integer.
The Arduino has only a 16 bit integer by default. Your PC has a 32 or even 64 bit integer by default.

The C++ standard requires defining certain names for variable sizes if the architecture supports them. These are done using typedef. uint32_t is whatever type is an unsigned 32-bit integer. On an AVR, that is equivalent to unsigned long. there are 4 typedefs provided for each signed and unsigned integers:

int8_t = char
int16_t = int
int32_t = long
int64_t = long long

uint8_t = unsigned char
uint16_t = unsigned int
uint32_t = unsigned long
uint64_t = unsigned long long

There are also two additional typedefs required, representing the largest-sized integral variables the compiler allows:

intmax_t = int64_t
uintmax_t = uint64_t

The standard also specifies that without an type qualifiers, integer literals are assumed to be of type int. A signed int value on the AVR architecture is 16 bits, as you can see from the listings above, so only the bottom half of the constant was actually being stored in the variable; the top half was truncated off.

Casting the numbers to uint32_t promotes them to a 32-bit vale, and lets them fit.