C de la définition de Macros pour déterminer big endian ou little endian machine?
Est-il une ligne de définition de macro pour déterminer le boutisme de la machine. Je suis en utilisant le code suivant, mais en la convertissant en macro serait trop long.
unsigned char test_endian( void )
{
int test_var = 1;
unsigned char test_endian* = (unsigned char*)&test_var;
return (test_endian[0] == NULL);
}
- Pourquoi ne pas inclure le même code dans une macro?
- Vous ne pouvez pas déterminer de façon portable endianness avec le préprocesseur C seul. Vous aussi vous voulez
0
au lieu deNULL
dans votre test final, et de modifier l'un destest_endian
objets à autre chose :-). - Pourquoi avez-vous besoin d'une macro?
- Aussi pourquoi un macro-elle nécessaire? Fonction Inline ferait la même chose, et il est beaucoup plus sûr.
- Est-ce un casse-tête/devoir à la maison? Normalement, vous ne devriez pas réellement besoin de s'inquiéter à propos de l'endianness de votre plate-forme.
- une macro est intéressante car sa valeur peut être connu au moment de la compilation, ce qui signifie que vous pouvez utiliser votre plate-forme de stockage de contrôle de l'instanciation d'un modèle, par exemple, ou peut-être même de sélectionner les différents blocs de code avec un
#if
directive. - Lors de l'écriture d'une application réseau ou une application qui exporte des données binaires dans un fichier, sachant que le stockage et correctement la manipulation de conversions est critique. Par exemple, si un Sun SPARC (big endian) et un serveur d'Intel x86 (little endian) serveur de swap de données binaires, l'un des deux devra convertir les données seront mal interprétés. Vous pouvez utiliser
ntohl()
,htonl()
,ntohs()
, ouhtons()
, mais ils ne poignée de 32 bits et 16 bits types de données. - Le format des données sur le fil doit être connues format spécifié (généralement de réseau de commande). Vous n'avez pas besoin de connaître le boutisme de votre plate-forme pour écrire à ce format, vous pouvez écrire endian-agnostique code par l'écriture d'un octet à la fois (par exemple,
fputc((value >> 24) & 0xFF, fp), fputc((value >> 16) & 0xFF, fp)
...) - C'est vrai, mais inefficace. Si j'ai un little-endian cpu, et je suis en train d'écrire little-endian données au fil ou à un fichier, je préfère éviter le déballage et le remballage de données sans but. J'ai utilisé pour écrire des pilotes vidéo pour une vie. Il est extrêmement important lors de l'écriture des pixels à une carte vidéo pour optimiser chaque endroit que vous le pouvez.
Vous devez vous connecter pour publier un commentaire.
Code de l'appui octets arbitraires ordres, prêt à être mis dans un fichier appelé
order32.h
:Que vous devriez vérifier pour little endian systèmes par le biais de
char
? Mieux utiliseruint8_t
et échouer si ce type n'est pas disponible (ce qui peut être vérifié par#if UINT8_MAX
). Notez queCHAR_BIT
est indépendant deuint8_t
.4
dansbytes[4]
? Si le code est compilé sur différentes plates-formes, pourquoi utiliser cette hypothèse? Mieux utilisersizeof(some_integer)
de conduirechar
taille de la matrice.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Si vous avez un compilateur qui prend en charge C99 composé de littéraux:
ou:
En général, cependant, vous devriez essayer d'écrire du code qui ne dépend pas de l'endianness de la plate-forme hôte.
Exemple de l'hôte-boutisme indépendant de la mise en œuvre de
ntohl()
:ntohl
d'une façon qui ne dépend pas de l'endianness de la plate-forme hôte.ntohl
mise en œuvre.IS_BIG_ENDIAN
dépend le code de littéraux de chaîne étant aligné à 16 bits de limites ou de la plate-forme supportant mal alignées accès à 16 bits quantités. Ce n'est pas entièrement portable hypothèse (notamment sur les BRAS des plates-formes).Il n'y a pas de norme, mais sur beaucoup de systèmes, y compris
<endian.h>
va vous donner quelques définit les chercher.#if __BYTE_ORDER == __LITTLE_ENDIAN
et#elif __BYTE_ORDER == __BIG_ENDIAN
. Et de générer un#error
elsewise.<endian.h>
n'est pas disponible sur Windowsendian.h
sauf__APPLE__
ou_WIN32
est défini.#if BYTE_ORDER == LITTLE_ENDIAN
(ouBIG_ENDIAN
) sans traits de soulignement avant de les noms._BYTE_ORDER
est uniquement pour le système d'en-têtes.__BYTE_ORDER
n'existe pas.Pour détecter l'endianness au moment de l'exécution, vous devez être en mesure de se référer à la mémoire. Si vous vous en tenez à la norme C, declarating une variable en mémoire nécessite une déclaration, mais le retour d'une valeur exige une expression. Je ne sais pas comment faire cela dans une seule macro—c'est pourquoi gcc a des extensions 🙂
Si vous êtes désireux d'avoir un .h fichier, vous pouvez définir
et puis vous pouvez utiliser le
ENDIANNESS
macro que vous.Si vous voulez seulement de s'appuyer sur le préprocesseur, vous devez trouver la liste des symboles prédéfinis. Préprocesseur l'arithmétique n'a pas de notion d'adressage.
GCC sur Mac définit
__LITTLE_ENDIAN__
ou__BIG_ENDIAN__
Ensuite, vous pouvez ajouter plus de préprocesseur directives conditionnelles basées sur la plate-forme de détection comme
#ifdef _WIN32
etc.#define __BIG_ENDIAN__ 1
et#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Cette macro semble être un bruit caractéristique, pas un gcc fonctionnalité. Legcc
commande dans certains Mac n'est pas gcc, c'est clang.Je crois que c'est ce qui était demandé.
J'ai uniquement testé sur un little endian machine sous msvc.
Quelqu'un s'il vous plait confirmer sur une machine big endian.
Comme une note de côté (compilateur spécifique), avec un agressif compilateur, vous pouvez utiliser "l'élimination du code mort" optimisation pour obtenir le même effet qu'un moment de la compilation
#if
comme suit:Ci-dessus repose sur le fait que le compilateur reconnaît les valeurs de constante au moment de la compilation, entièrement supprime le code à l'intérieur
if (false) { ... }
et remplace le code commeif (true) { foo(); }
avecfoo();
Le pire des cas: le compilateur ne fait pas de l'optimisation, vous obtenez toujours le code est correct, mais un peu plus lent.'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
et il générera une erreur. (Clang et ce en particulier:-Wfour-char-constants -Werror
)Si vous êtes à la recherche d'un moment de la compilation, test et vous utilisez gcc, vous pouvez le faire:
Voir la documentation de gcc pour plus d'informations.
__BYTE_ORDER__
est disponible depuis la GCC 4.6Vous peut en effet, l'accès à la mémoire d'un objet temporaire à l'aide d'un composé littéral (C99):
GCC permettra d'évaluer au moment de la compilation.
#if __STDC_VERSION__ >= 199901L
.Le "C library" offre des fonctions pour gérer endian'ness. À savoir htons(), htonl(), ah() et ntohl() ...où n est le "réseau" (ie. big-endian), et h est "accueil" (ie. le endian'ness de la machine qui exécute le code).
Ces apparente "fonctions" sont (généralement) défini comme les macros [voir <netinet/in.h>], donc il n'y a pas de gestion d'exécution de leur utilisation.
Les macros suivantes utilisation de ces "fonctions" pour évaluer endian'ness.
En outre:
La seule fois que j'ai besoin de savoir le endian'ness d'un système, c'est quand j'écris une variable [d'un fichier/d'autres] qui peut être lu par un autre système de inconnu-boutiste'ness (pour la croix-plate-forme de compatibilité) ...Dans de tels cas, vous préférerez peut-être utiliser la endian directement les fonctions de:
Utiliser une fonction en ligne plutôt que d'une macro. En outre, vous avez besoin de stocker quelque chose dans la mémoire qui est un pas-très-bel effet d'une macro.
Vous pouvez convertir une macro à l'aide d'un statique ou variable globale, comme ceci:
s_endianess
mis à 1 pour commencer?Bien qu'il n'existe pas de portable #define ou quelque chose de fier, plates-formes offrent des fonctions standard de conversion vers et à partir de votre "hôte" endian.
Généralement, vous ne le stockage sur disque ou sur le réseau à l'aide du réseau des endian", qui est GRAND endian, et local de calcul à l'aide d'hôte endian (qui sur x86 est PEU endian). Vous utilisez
htons()
etntohs()
et amis pour convertir entre les deux.Essayez ceci:
N'oubliez pas que l'endianness n'est pas toute l'histoire - la taille de
char
pourrait ne pas être en 8 bits (par exemple, DSP), en complément à deux de la négation n'est pas garantie (par ex. Cray), un strict alignement peut être nécessaire (par exemple, SPARC, également au BRAS de ressorts en moyen-endian lorsque non alignés), etc, etc.Il pourrait être une meilleure idée pour une cible spécifique architecture du PROCESSEUR à la place.
Par exemple:
Noter que cette solution est également pas ultra-portable, malheureusement, car cela dépend du compilateur-définitions spécifiques (il n'y a pas de norme, mais voici une belle compilation de ces définitions).
Veuillez faire attention à ce que la plupart des réponses ici ne sont pas portable, car les compilateurs d'aujourd'hui permettra d'évaluer les réponses en temps de compilation (dépend de l'optimisation) et de retourner une valeur spécifique sur la base d'un endianness, tandis que la machine réelle, endianness peuvent différer. Les valeurs sur lesquelles l'endianness est testé, n'atteignent jamais la mémoire du système donc le vrai code exécuté donnera le même résultat quel que soit l'endianness.
Pour exemple, en ARM Cortex-M3; la mise en œuvre de l'endianness reflètent un bit d'état AIRCR.BOUTISME et le compilateur ne peut pas savoir cette valeur au moment de la compilation.
Compilation de sortie pour certaines des réponses suggérées ici:
https://godbolt.org/z/GJGNE2 pour cette réponse,
https://godbolt.org/z/Yv-pyJ pour cette réponse, et ainsi de suite.
Pour le résoudre, vous devrez utiliser le
volatile
qualificatif.Yogeesh H T
's réponse est le plus proche de celui d'aujourd'hui est la vraie vie, mais depuisChristoph
suggère solution plus complète, une légère correction à son réponse rendrait la réponse complète, il suffit d'ajoutervolatile
à la déclaration de l'union:static const volatile union
.Cela permettrait d'assurer le stockage et la lecture de la mémoire, qui est nécessaire pour déterminer l'endianness.
Ma réponse n'est pas comme demandé, mais Il est vraiment simple de trouver si votre système est en little endian ou big endian?
Code:
C Code pour vérifier si un système est en little-endian ou big-indien.
Macro pour trouver endiannes
ou