J’ai parfois l’impression qu’en tant que bioinformaticien occasionnel, je passe davantage de temps à convertir des fichiers de données d’un format à un autre (la bioinformatique n’étant pas avare en matière de formats de données) qu’à faire des choses intéressantes avec les données contenues dans lesdits fichiers.
La plupart du temps, les formats en question sont textuels (GenBank, Fasta, etc.). Mais il m’arrive de tomber sur des formats binaires, généralement issus de logiciels propriétaires. Et là, peut alors se poser la question du boutisme (endianness ; certains auteurs parlent aussi de sexe des octets) des valeurs numériques que l’on trouve dans ces formats, dès lors que celles-ci sont codées sur plus d’un octet.
Cette note est un simple aide-mémoire sur cette question.
Un nombre stocké sur deux octets (par exemple 0xCAFE
)
peut être représenté en mémoire de deux façons différentes :
0xCA 0xFE
) ;0xFE 0xCA
).Cela s’applique aussi aux nombres stockés sur 4 et 8 octets, à ceci près qu’il existe plus de deux formats pour ces nombres, puisqu’on peut jouer non seulement avec l’ordre des octets mais aussi avec l’ordre des mots de deux et quatre octets.
Ainsi, le nombre 0xDECAFBAD
peut être représenté des
manières suivantes :
0xDE 0xCA 0xFB 0xAD
(grand-boutien) ;0xAD 0xFB 0xCA 0xDE
(petit-boutien) ;0xFB 0xAD 0xDE 0xCA
(petit-boutien de mots
grand-boutiens) ;0xCA 0xDE 0xAD 0xFB
(grand-boutien de mots
petit-boutiens).Dans le reste de cette note, je négligerai ces deux derniers cas pour ne parler que des cas « simples » — et a priori les plus fréquents — de grand-boutisme et petit-boutisme au niveau des octets.
Chaque machine ou application décide librement et arbitrairement de ses préférences boutistes. Les processeurs Intel sont notoirement petit-boutistes, tandis que les processeurs PowerPC qui armaient les anciennes générations de machines Apple étaient grand-boutistes. Plusieurs protocoles réseau utilisent le format grand-boutien, ce qui vaut à ce format d’être parfois appelé (notamment dans les fonctions de conversion, cf. ci-dessous) le network order (par opposition au host order, le format utilisé par la machine).
Pour les projets autoconfisqués, la macro
Autoconf AC_C_BIGENDIAN
permet de tester
l’endianness de la machine cible lors de la configuration
des sources.
Utilisée le plus simplement sans paramètres, cette macro définit le
symbole WORDS_BIGENDIAN
si la machine cible est
grand-boutiste.
dnl configure.ac AC_C_BIGENDIAN /* Dans le code C */ #ifdef WORDS_BIGENDIAN /* machine grand-boutiste */ #else /* machine petit-boutiste */ #endif
Le standard POSIX définit une famille de quatre fonctions permettant de passer du network order (format grand-boutien) au host order (format de la machine, quel qu’il soit) et inversement :
htonl
(host to network long) convertit un
entier sur 32 bits (long word) depuis vers le format de la
machine vers le format réseau ;htons
(host to nework short) fait de même,
mais pour un entier codé sur 16 bits (short word) ;ntohl
(network to host long) convertit un
entier sur 32 bits depuis le format réseau vers le format de la
machine ;ntohs
(network to host short) fait de même,
mais pour un entier codé sur 16 bits.Ces fonctions sont normalement déclarées dans
arpa/inet.h
. On notera qu’il n’existe pas de variantes de
ces fonctions pour les entiers codés sur 64 bits.
endian.h
(glibc, *BSD)La bibliothèque C GNU définit dans son en-tête endian.h
une famille de
fonctions (non-standard) permettant de convertir des entiers codés
sur 16, 32 ou 64 bits entre le format de la machine et les formats
petit- et grand-boutien :
htobeNN
(host to big-endian NN-bits)
convertit un entier sur NN bits (avec NN = 16, 32 ou 64)
depuis le format de la machine vers le format grand-boutien ;htoleNN
(host to little-endian NN-bits)
convertit un entier depuis le format de la machine vers le format
petit-boutien ;beNNtoh
(big-endian NN-bits to host)
convertit un entier depuis le format grand-boutien vers le format de
la machine ;leNNtoh
(little-endian NN-bits to host)
convertit un entier depuis le format petit-boutien vers le format de
la machine.Ces fonctions existent aussi sur les systèmes BSD, où elles sont
définies dans l’en-tête sys/endian.h
.
byteswap.h
(glibc)La bibliothèque C GNU définit aussi dans son en-tête
byteswap.h
trois
macros (non-standard) permettant d’inverser l’ordre des octets
dans des entiers codés sur 16, 32 et 64 bits : bswap_16
,
bswap_32
et bswap_64
.
Si possible, ces macros sont implémentées à l’aide d’instructions
dédiées du processeur (instruction
bswap
sur les processeurs i486 et supérieurs).
À la différence des fonctions précédentes, ces macros renversent
systématiquement l’ordre des octets sans tenir compte du format
utilisé par la machine ; elles ne doivent donc être utilisées que si
l’on sait que l’on doit manipuler des entiers dans un format différent
de celui de l’hôte — par exemple en utilisant le symbole
WORDS_BIGENDIAN
produit par la macro Autoconf
AC_BIG_ENDIAN
, cf. ci-dessus).