Undefined behaviour and endianness
Undefined behaviour, such as signed overflow, out-of-bounds access or reading an uninitialised variable, lets the compiler do anything, and optimisers rely on it never happening. Endianness is the order of a value's bytes in memory. Build multi-byte values from bytes with shifts, and code works on any host.
Undefined behaviour
For some operations the C standard sets no requirement at all: signed integer overflow, indexing outside an array, dereferencing NULL, reading an uninitialised local, shifting by the type's width or more, and accessing an object through an incompatible pointer type. The compiler may assume these never happen and optimise on that basis. A check written as if (x + 1 < x) for a signed x can be removed entirely, because it could only be true after an overflow.
Endianness
A 32-bit value occupies four bytes. A little-endian machine stores the least significant byte at the lowest address, a big-endian one the most significant byte. Most microcontrollers in use today, including Arm Cortex-M parts as they are usually configured, and x86 PCs are little-endian. Many network protocols send the most significant byte first, called network byte order.
Copying wire bytes straight into a uint32_t gives a value that depends on the host. Building the value with shifts does not: read_be32 gives 0x12345678 on every machine. Cast each byte to uint32_t before shifting, because p[0] << 24 would shift a promoted int, and a top bit of 1 would overflow it.
#include <stdint.h>#include <stdio.h>#include <string.h>/* Builds the value from bytes, so it gives the same result on any host. */static uint32_t read_be32(const uint8_t *p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];}int main(void) { const uint8_t wire[4] = {0x12, 0x34, 0x56, 0x78}; /* big-endian on the wire */ uint32_t copied; memcpy(&copied, wire, sizeof copied); /* host byte order */ printf("memcpy: 0x%08lX\n", (unsigned long)copied); printf("read_be32: 0x%08lX\n", (unsigned long)read_be32(wire)); uint32_t one = 1; uint8_t first; memcpy(&first, &one, 1); printf("this host is %s-endian\n", first ? "little" : "big"); return 0;}
memcpy: 0x78563412 read_be32: 0x12345678 this host is little-endian