Existe-t-il une définition de macro sur une ligne pour déterminer l'endianité de la machine. J'utilise le code suivant mais le convertir 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] == 0);
}
c
architecture
macros
endianness
manav mn
la source
la source
0
au lieu deNULL
dans votre test final, et changer l'un destest_endian
objets en autre chose :-).#if
directive.Réponses:
Code prenant en charge les ordres d'octets arbitraires, prêt à être placé dans un fichier appelé
order32.h
:Vous vérifieriez les systèmes little endian via
la source
char
? Meilleure utilisationuint8_t
et échec si ce type n'est pas disponible (ce qui peut être vérifié par#if UINT8_MAX
). Notez queCHAR_BIT
c'est indépendant deuint8_t
.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Si vous avez un compilateur qui prend en charge les littéraux composés C99:
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 d'implémentation indépendante de l'hôte-endianness de
ntohl()
:la source
ntohl
d'une manière qui ne dépend pas de l'endianness de la plate-forme hôte.Il n'y a pas de norme, mais sur de nombreux systèmes,
<endian.h>
cela vous donnera quelques définitions à rechercher.la source
#if __BYTE_ORDER == __LITTLE_ENDIAN
et#elif __BYTE_ORDER == __BIG_ENDIAN
. Et générer un#error
autre.<endian.h>
n'est pas disponible sur Windowsendian.h
sauf si__APPLE__
ou_WIN32
est défini.#if BYTE_ORDER == LITTLE_ENDIAN
(ouBIG_ENDIAN
) sans traits de soulignement avant les noms._BYTE_ORDER
est uniquement pour les en-têtes système.__BYTE_ORDER
n'existe pas.Pour détecter l'endianness au moment de l'exécution, vous devez pouvoir vous référer à la mémoire. Si vous vous en tenez au standard C, la déclaration d'une variable en mémoire nécessite une instruction, mais le retour d'une valeur nécessite une expression. Je ne sais pas comment faire cela dans une seule macro - c'est pourquoi gcc a des extensions :-)
Si vous souhaitez avoir un fichier .h, vous pouvez définir
puis vous pouvez utiliser la
ENDIANNESS
macro comme vous le souhaitez.la source
Si vous voulez vous fier uniquement au préprocesseur, vous devez trouver la liste des symboles prédéfinis. L'arithmétique du préprocesseur n'a pas de concept d'adressage.
GCC sur Mac définit
__LITTLE_ENDIAN__
ou__BIG_ENDIAN__
Ensuite, vous pouvez ajouter plus de directives conditionnelles de préprocesseur basées sur la détection de plate-forme comme
#ifdef _WIN32
etc.la source
#define __BIG_ENDIAN__ 1
et#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Cette macro semble être une fonction clang, pas une fonction gcc. Lagcc
commande sur certains Mac n'est pas gcc, elle résonne.Je crois que c'est ce qui a été demandé. Je n'ai testé cela que sur une petite machine endian sous msvc. Quelqu'un peut confirmer sur une machine big endian.
En remarque (spécifique au compilateur), avec un compilateur agressif, vous pouvez utiliser l'optimisation "d'élimination de code mort" pour obtenir le même effet qu'un temps de compilation
#if
comme ceci:Ce qui précède repose sur le fait que le compilateur reconnaît les valeurs constantes au moment de la compilation, supprime entièrement le code à l'intérieur
if (false) { ... }
et remplace le code commeif (true) { foo(); }
avecfoo();
Le pire des cas: le compilateur ne fait pas l'optimisation, vous obtenez toujours du code correct mais un peu plus lent.la source
'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
et il y aura une erreur. (Clang et ce en particulier:-Wfour-char-constants -Werror
)Si vous recherchez un test de compilation et que vous utilisez gcc, vous pouvez faire:
Consultez la documentation de gcc pour plus d'informations.
la source
__BYTE_ORDER__
est disponible depuis GCC 4.6Vous pouvez en effet accéder à la mémoire d'un objet temporaire en utilisant un littéral composé (C99):
Quel GCC évaluera au moment de la compilation.
la source
#if __STDC_VERSION__ >= 199901L
.La 'bibliothèque réseau C' offre des fonctions pour gérer l'endian'ness. A savoir htons (), htonl (), ntohs () et ntohl () ... où n est "network" (ie. Big-endian) et h est "host" (ie. Endian'ness de la machine exécutant le code).
Ces «fonctions» apparentes sont (généralement) définies comme des macros [voir <netinet / in.h>], il n'y a donc pas de surcharge d'exécution pour les utiliser.
Les macros suivantes utilisent ces 'fonctions' pour évaluer l'endian'ness.
En outre:
La seule fois où j'ai besoin de connaître le caractère endian d'un système, c'est lorsque j'écris une variable [dans un fichier / autre] qui peut être lue par un autre système dont le caractère endian est inconnu (pour une compatibilité multiplateforme ) ... Dans de tels cas, vous préférerez peut-être utiliser directement les fonctions endian:
la source
Utilisez une fonction en ligne plutôt qu'une macro. De plus, vous devez stocker quelque chose en mémoire, ce qui est un effet secondaire pas très agréable d'une macro.
Vous pouvez le convertir en une macro courte en utilisant une variable statique ou globale, comme ceci:
la source
s_endianess
défini sur 1 pour commencer?Bien qu'il n'y ait pas de #define portable ou quelque chose sur lequel s'appuyer, les plates-formes fournissent des fonctions standard pour la conversion vers et depuis votre endian «hôte».
En règle générale, vous effectuez le stockage - sur disque ou réseau - en utilisant 'network endian', ce qui est BIG endian, et le calcul local en utilisant host endian (qui sur x86 est LITTLE endian). Vous utilisez
htons()
etntohs()
et vos amis pour convertir entre les deux.la source
la source
N'oubliez pas que l'endianness n'est pas toute l'histoire - la taille de
char
peut ne pas être de 8 bits (par exemple DSP), la négation du complément à deux n'est pas garantie (par exemple Cray), un alignement strict peut être requis (par exemple, SPARC, ARM passe également au milieu -endian lorsqu'il pas aligné), etc., etc.Il pourrait être préférable de cibler une architecture de processeur spécifique place.
Par exemple:
Notez que cette solution n'est malheureusement pas non plus ultra-portable, car elle dépend de définitions spécifiques au compilateur (il n'y a pas de standard, mais voici une belle compilation de ces définitions).
la source
Essaye ça:
la source
Veuillez faire attention que la plupart des réponses ici ne sont pas portables, car les compilateurs aujourd'hui évalueront ces réponses au moment de la compilation (dépend de l'optimisation) et retourneront une valeur spécifique basée sur une endianité spécifique, alors que l'endianité réelle de la machine peut différer. Les valeurs sur lesquelles l'endianité est testée n'atteindront jamais la mémoire système, donc le code réel exécuté renverra le même résultat quelle que soit l'endianité réelle.
Par exemple , dans ARM Cortex-M3, l'endianness implémentée se reflétera dans un bit d'état AIRCR.ENDIANNESS et le compilateur ne peut pas connaître cette valeur au moment de la compilation.
Sortie de compilation 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 cela 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 l' utilisation réelle de la vie d'aujourd'hui, mais commeChristoph
suggère une solution plus complète, une légère correction à sa réponse serait la réponse complète, il suffit d' ajoutervolatile
à la déclaration syndicale:static const volatile union
.Cela assurerait le stockage et la lecture à partir de la mémoire, ce qui est nécessaire pour déterminer l'endianité.
la source
Si vous videz le préprocesseur #defines
Vous pouvez généralement trouver des choses qui vous aideront. Avec une logique de compilation.
Cependant, divers compilateurs peuvent avoir des définitions différentes.
la source
Ma réponse n'est pas celle demandée mais il est vraiment simple de trouver si votre système est petit ou gros boutien?
Code:
la source
C Code pour vérifier si un système est petit-boutiste ou grand-indien.
la source
Macro pour trouver des endiannes
ou
la source