Interestingly (and pedantically), the code from the otherwise excellent "Byte order fallacy" article technically contains undefined behavior in C on machines where int is 32 bits wide (which is almost everything nowadays).
Consider this example of extracting a 32-bit int encoded as little endian:
#include <stdio.h>
int main(void)
{
unsigned char data[4] = { 0, 0, 0, 128 };
unsigned int i;
// the line of code from the article:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
printf("%x\n", i);
}
Compiling this with either gcc or clang using "-fsanitize=undefined" triggers this runtime error: test.c:9:61: runtime error: left shift of 128 by 24 places cannot be represented in type 'int'
That happens because, even though the bytes are unsigned as the article requires (using uint8_t instead of unsigned char has the same problem), they are promoted to (signed) int before the left shift as part of automatic integer promotion. When the left shift by 24 happens, it puts an 1 into the sign bit of the int, which is undefined behavior. Later the int is converted to unsigned (using implementation-defined behavior, which luckily is sane on all popular compilers), but by then it's already too late.The solution is to change the code slightly:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | ((unsigned)data[3]<<24);
This prevents the promotion from unsigned char (or uint8_t) to int by explicitly casting it to an unsigned int, which can then be safely shifted left by 24.