À propos du code source de htonl

Je me réfère au code suivant:

u_int32_t htonl(u_int32_t x) { #if BYTE_ORDER == LITTLE_ENDIAN u_char *s = (u_char *)&x; return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); #else return x; #endif } 

Par exemple:

 unsigned int x = 0x01020304 

dans un petit système final:

 s[0] = 0x04, s[1] = 0x03, s[2] = 0x02, s[3] = 0x01 

puis retourne:

 (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); 

la valeur de retour , par exemple:

 u_int32t_t result = (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); 

dans la mémoire système:

 u_char *r = (u_char *)&result 

alors:

 r[0] = 0x04, r[1] = 0x03, r[2] = 0x02, r[3] = 0x02 

Est-ce correct?

Htonl a pour but de convertir la représentation de la valeur en ordre d’octet réseau – big endian. Supposons que vous travaillez sur la machine intel et que votre ordre d’octets soit peu important (le code dans l’instruction if est exécuté). Vous pouvez écrire un code factice qui vérifie votre compréhension de son fonctionnement:

 #include #include  int main() { u_int32_t x = 16909060; //0x01020304 u_char* s = (u_char*)&x; printf("%x\n",x); printf("s[0]: %x\n",s[0]); printf("s[1]: %x\n",s[1]); printf("s[2]: %x\n",s[2]); printf("s[3]: %x\n",s[3]); printf("s[0] << 24: %x\n", s[0] << 24); printf("s[1] << 16: %x\n", s[1] << 16); printf("s[2] << 8: %x\n", s[2] << 8); printf("final: %x\n", s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); return 0; } 

sortie:

 1020304 s[0]: 4 s[1]: 3 s[2]: 2 s[3]: 1 s[0] << 24: 4000000 s[1] << 16: 30000 s[2] << 8: 200 final: 4030201 

L'opérateur OR a la table de vérité suivante:

 ab out 0 0 0 0 1 1 1 0 1 1 1 1 

alors voici le calulation

 0000 0100 0000 0000 0000 0000 0000 0000 | //s[0] << 24 0000 0000 0000 0011 0000 0000 0000 0000 | //s[1] << 16 0000 0000 0000 0000 0000 0010 0000 0000 | //s[2] << 8 0000 0000 0000 0000 0000 0000 0000 0001 = //s[3] _________________________________________ 0000 0100 0000 0011 0000 0010 0000 0001 

Pour résumer, 0x01020304 dans différents ordres d'octets:

  • little endian: 04 03 02 01 (LSB a la plus petite adresse)
  • big endian: 01 02 03 04 (MSB a la plus petite adresse)