Problèmes de portabilité pour les conversions d'ordre d'octets réseau d'entiers de 64 bits en C
En C, il est nécessaire de convertir des entiers de 64 bits à « l'ordre des octets du réseau » pour des applications spécifiques, telles que la mise en œuvre du protocole Memcache. Malgré l'existence de la fonction htonl() pour convertir des entiers 32 bits, une fonction similaire pour les entiers 64 bits (htonll()) reste insaisissable.
Considérations sur les fonctions standard
Malheureusement, il n'existe actuellement aucune fonction standard portable en C capable d'effectuer des conversions de l'ordre des octets du réseau 64 bits. Cette absence crée le besoin d'implémentations personnalisées.
Implémentation personnalisée
Pour implémenter htonll(), nous devons d'abord déterminer le caractère boutien du système. Une méthode fiable consiste à évaluer la valeur d'une variable entière avec un ordre d'octets connu (par exemple, 42) au moment de l'exécution :
<code class="cpp">static const int num = 42; bool isBigEndian = (*reinterpret_cast<const char *>(&num) == num);</code>
Ensuite, nous pouvons effectuer la conversion en fonction du caractère boutien :
<code class="cpp">uint64_t htonll(uint64_t value) { if (isBigEndian) { const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32)); const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL)); return (static_cast<uint64_t>(low_part) << 32) | high_part; } else { return value; } }
Macros pour la portabilité
Alternativement, les macros peuvent fournir un moyen concis de définir htonll() et son homologue, ntohll() :
<code class="cpp">#define htonll(x) ((1 == htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) #define ntohll(x) ((1 == ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))</code>
Ces les macros s'appuient sur le comportement intrinsèque de l'ordre des octets du système pour déterminer l'échange d'octets nécessaire.
Macros spécifiques au compilateur
Certains compilateurs et systèmes d'exploitation fournissent des macros spécifiques pour déterminer l'endianité . Par exemple, sur les systèmes qui le prennent en charge, nous pouvons utiliser :
<code class="cpp">#if __BIG_ENDIAN__ # define htonll(x) (x) # define ntohll(x) (x) #else # define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) # define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) #endif</code>
En employant ces techniques, les implémentations personnalisées de htonll() et ntohll() peuvent être rendues portables sur divers systèmes et compilateurs.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!