Aggiungendo i miei 10 centesimi a questa risposta:
u64 indica un valore di '64 bit senza segno', quindi, a seconda dell'architettura in cui il codice verrà eseguito/compilato, deve essere definito in modo diverso per essere realmente lungo 64 bit.
Ad esempio, su una macchina x86, un unsigned long è lungo 64 bit, quindi u64 per quella macchina potrebbe essere definito come segue:
typedef unsigned long u64;
Lo stesso vale per u32 . Su una macchina x86, unsigned int è lungo 32 bit, quindi u32 per quella macchina potrebbe essere definito come segue:
typedef unsigned int u32;
Generalmente troverai typedef dichiarazione per questi tipi su un types.h file che corrisponde all'architettura in cui stai compilando il tuo codice sorgente.
Spesso quando si lavora vicino all'hardware o quando si tenta di controllare la dimensione/formato di una struttura dati è necessario avere un controllo preciso della dimensione dei numeri interi.
Per quanto riguarda u8 rispetto a uint8_t , questo semplicemente perché Linux è precedente a <stdint.h> essendo disponibile in C, che tecnicamente è un C99-ismo, ma nella mia esperienza è disponibile sulla maggior parte dei compilatori moderni anche nelle loro modalità ANSI-C / C89.