2008-11-11 15 views
28

J'ai un peu de code de sérialisation de bas niveau qui est modélisé, et j'ai besoin de connaître l'endianness du système à compiletime évidemment (parce que les modèles se spécialise basé sur l'endianness du système).Existe-t-il un moyen de faire une assertion à la compilation de style C++ pour déterminer l'endianness de la machine?

En ce moment j'ai un en-tête avec une certaine définition de plate-forme, mais je préférerais faire des assertions sur l'endianness avec un test basé sur un modèle (comme static_assert ou boost_if). Raison d'être mon code devra être compilé et exécuté sur un large éventail de machines, de nombreux fournisseurs spécialisés, et probablement des appareils qui n'existent pas en 2008, donc je ne peux pas vraiment deviner ce qui pourrait avoir besoin d'aller dans cette tête d'années en bas de la route. Et puisque le code-base a une durée de vie prévue d'environ 10 ans. Donc je ne peux pas suivre le code pour toujours.

J'espère que cela clarifie ma situation.

Alors, est-ce que quelqu'un connaît un test de compilation qui peut déterminer l'endianness, sans s'appuyer sur des définitions spécifiques au fournisseur?

Répondre

18

Si vous utilisez autoconf, vous pouvez utiliser la macro AC_C_BIGENDIAN, qui est assez garanti pour fonctionner (réglage de la WORDS_BIGENDIAN définir par défaut)

alternativement, vous pouvez essayer quelque chose comme ce qui suit (extrait de autoconf) pour obtenir un test qui sera probablement pas être optimisés (GCC, au moins, supprime l'autre branche)

int is_big_endian() 
{ 
    union { 
     long int l; 
     char c[sizeof (long int)]; 
    } u; 

    u.l = 1; 

    if (u.c[sizeof(long int)-1] == 1) 
    { 
     return 1; 
    } 
    else 
     return 0; 
} 
+2

Merci, c'est une bonne astuce. Et je pense que je peux l'appliquer avec un peu de réingénierie. pas encore sûr, mais c'est une bonne avance. –

5

Hmm, c'est une question intéressante. Mon pari est que ce n'est pas possible. Je pense que vous devez continuer à utiliser des macros, et aller avec BOOST_STATIC_ASSERT(!BIG_ENDIAN);, ou static_assert en C++ 0x. La raison pour laquelle je pense que c'est parce que les endian'nes est une propriété si votre environnement d'exécution. Cependant, static_assert est considéré au moment de la compilation.

Je vous suggère de regarder dans le code du nouvel éditeur de liens ELF GNU gold. Ian Lance Taylor, son auteur, a utilisé des modèles pour sélectionner la bonne endianness au moment de la compilation, afin d'assurer des performances optimales au moment de l'exécution. Il instancie explicitement tous les endians possibles, de sorte qu'il a toujours une compilation séparée (pas tous les modèles dans les en-têtes) de la définition et de la déclaration du modèle. Son code est excellent.

+0

Oui Je n'ai pas été en mesure de comprendre moi-même, et comme vous le dites, il pourrait même ne pas être possible . Mais j'ai vu l'impossible fait auparavant pour d'autres situations ... alors peut-être, peut-être que quelqu'un pourrait venir avec une bonne idée ici :) –

+0

Pourquoi ne pas ce travail: '#define IS_LITTLE_ENDIAN char (0x00ff)'. Cette solution est un peu inspirée par la réponse de @ MichaelBurr. Cela fonctionne bien avec les modèles, [démo] (http://ideone.com/JAS7mO). Supposons 'uint8_t' à la place de' char' pour être précis. – iammilind

+1

@iamm Je ne pense pas qu'il soit possible de construire des bitpatterns en C ou en C++. Vous construisez la valeur 255 et la transtypez en char. Même si C vous permettait de spécifier une représentation binaire, vous devez toujours convaincre le compilateur d'interpréter ce bitmap comme contenu de la mémoire et de le charger dans un registre plutôt que de l'avoir comme valeur immédiate. Pour le registre-exclusif comme la troncature et l'extension zéro, l'endianness est sans importance IIRC. –

18

Il n'y a pas de façon portable de faire cela au moment de la compilation, votre meilleur pari est probablement d'utiliser le Boostendian macros ou d'émuler les méthodes qu'ils utilisent.

+0

Merci pour le lien vers l'en-tête. C'est une bonne référence. Et semblable à ce que j'ai. –