Gibt es eine einzeilige Makrodefinition, um die Endianness der Maschine zu bestimmen? Ich verwende den folgenden Code, aber die Konvertierung in ein Makro wäre zu lang.
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
quelle
quelle
0
stattNULL
in Ihrem letzten Test eines dertest_endian
Objekte in etwas anderes ändern :-).#if
Direktive auswählen können .Antworten:
Code, der beliebige Bytereihenfolgen unterstützt und bereit ist, in eine Datei mit dem Namen
order32.h
:Sie würden über nach kleinen Endian-Systemen suchen
quelle
char
? Besser verwendenuint8_t
und fehlschlagen, wenn dieser Typ nicht verfügbar ist (was von überprüft werden kann#if UINT8_MAX
). Beachten Sie, dassCHAR_BIT
unabhängig vonuint8_t
.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Wenn Sie einen Compiler haben, der zusammengesetzte C99-Literale unterstützt:
oder:
Im Allgemeinen sollten Sie jedoch versuchen, Code zu schreiben, der nicht von der Endlichkeit der Host-Plattform abhängt.
Beispiel für eine vom Host-Endianness unabhängige Implementierung von
ntohl()
:quelle
ntohl
auf eine Weise implementieren , die nicht von der Endlichkeit der Host-Plattform abhängt.Es gibt keinen Standard, aber auf vielen Systemen
<endian.h>
gibt es einige Definitionen, nach denen Sie suchen müssen.quelle
#if __BYTE_ORDER == __LITTLE_ENDIAN
und#elif __BYTE_ORDER == __BIG_ENDIAN
. Und generieren Sie eine#error
andere.<endian.h>
ist nicht verfügbar unter Windowsendian.h
sofern__APPLE__
oder nicht_WIN32
definiert.#if BYTE_ORDER == LITTLE_ENDIAN
(oderBIG_ENDIAN
) keine Unterstriche vor den Namen._BYTE_ORDER
ist nur für Systemheader.__BYTE_ORDER
ist nicht vorhanden.Um Endianness zur Laufzeit zu erkennen, müssen Sie in der Lage sein, auf den Speicher zu verweisen. Wenn Sie sich an Standard C halten, ist für die Deklaration einer Variablen im Speicher eine Anweisung erforderlich, für die Rückgabe eines Werts ist jedoch ein Ausdruck erforderlich. Ich weiß nicht, wie man das in einem einzelnen Makro macht - deshalb hat gcc Erweiterungen :-)
Wenn Sie bereit sind, eine .h-Datei zu haben, können Sie diese definieren
und dann können Sie das
ENDIANNESS
Makro wie Sie wollen verwenden.quelle
Wenn Sie sich nur auf den Präprozessor verlassen möchten, müssen Sie die Liste der vordefinierten Symbole herausfinden. Präprozessorarithmetik hat kein Konzept der Adressierung.
GCC auf Mac definiert
__LITTLE_ENDIAN__
oder__BIG_ENDIAN__
Dann können Sie weitere Präprozessor-bedingte Anweisungen hinzufügen, die auf der Plattformerkennung basieren, wie z
#ifdef _WIN32
.quelle
#define __BIG_ENDIAN__ 1
und#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Dieses Makro scheint ein Clang-Feature zu sein, kein GCC-Feature. Dergcc
Befehl in einigen Macs ist nicht gcc, sondern klirrend.Ich glaube, darum wurde gebeten. Ich habe dies nur auf einer kleinen Endian-Maschine unter msvc getestet. Jemand bitte auf einer Big-Endian-Maschine bestätigen.
Als Randnotiz (compilerspezifisch) können Sie mit einem aggressiven Compiler die Optimierung "Dead Code Elimination" verwenden, um den gleichen Effekt wie bei einer Kompilierungszeit
#if
wie folgt zu erzielen :Das Obige beruht auf der Tatsache, dass der Compiler die konstanten Werte zur Kompilierungszeit erkennt, den Code vollständig entfernt
if (false) { ... }
und den Code wieif (true) { foo(); }
imfoo();
schlimmsten Fall ersetzt: Der Compiler führt die Optimierung nicht durch, Sie erhalten immer noch den richtigen Code, aber etwas langsamer.quelle
'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
und es wird ein Fehler auftreten. (Clang und dies insbesondere:-Wfour-char-constants -Werror
)Wenn Sie nach einem Test zur Kompilierungszeit suchen und gcc verwenden, können Sie Folgendes tun:
Weitere Informationen finden Sie in der gcc-Dokumentation .
quelle
__BYTE_ORDER__
ist verfügbar seit GCC 4.6Sie können tatsächlich mit einem zusammengesetzten Literal (C99) auf den Speicher eines temporären Objekts zugreifen:
Welcher GCC wird zur Kompilierungszeit ausgewertet?
quelle
#if __STDC_VERSION__ >= 199901L
.Die 'C-Netzwerkbibliothek' bietet Funktionen für die Endianität. Nämlich htons (), htonl (), ntohs () und ntohl () ... wobei n "Netzwerk" (dh Big-Endian) und h "Host" ist (dh die Endianität der Maschine, auf der das ausgeführt wird) Code).
Diese scheinbaren 'Funktionen' werden (allgemein) als Makros definiert [siehe <netinet / in.h>], sodass kein Laufzeitaufwand für ihre Verwendung entsteht.
Die folgenden Makros verwenden diese 'Funktionen', um die Endianität zu bewerten.
Zusätzlich:
Das einzige Mal, dass ich jemals die Endianität eines Systems kennen muss, ist das Ausschreiben einer Variablen [in eine Datei / andere], die von einem anderen System mit unbekannter Endianität eingelesen werden kann (aus Gründen der plattformübergreifenden Kompatibilität) ) ... In solchen Fällen bevorzugen Sie möglicherweise die direkte Verwendung der Endian-Funktionen:
quelle
Verwenden Sie eine Inline-Funktion anstelle eines Makros. Außerdem müssen Sie etwas im Speicher speichern, was ein nicht so schöner Nebeneffekt eines Makros ist.
Sie können es mit einer statischen oder globalen Variablen wie folgt in ein kurzes Makro konvertieren:
quelle
s_endianess
auf 1 gesetzt?Während es kein portables #define oder etwas gibt, auf das Sie sich verlassen können, bieten Plattformen Standardfunktionen für die Konvertierung zu und von Ihrem 'Host'-Endian.
Im Allgemeinen speichern Sie - auf Festplatte oder im Netzwerk - mithilfe von 'Netzwerk-Endian' ( BIG- Endian) und lokaler Berechnungen mit Host-Endian (auf x86 LITTLE- Endian). Sie verwenden
htons()
undntohs()
und Freunde, um zwischen den beiden zu konvertieren.quelle
quelle
Vergessen Sie nicht, dass Endianness nicht die ganze Geschichte ist - die Größe von
char
möglicherweise nicht 8 Bit (z. B. DSPs), die Negation von Zweierkomplementen ist nicht garantiert (z. B. Cray), möglicherweise ist eine strikte Ausrichtung erforderlich (z. B. SPARC, auch ARM springt in die Mitte) -endian wenn nicht ausgerichtet) usw. usw.Es ist möglicherweise besser, stattdessen auf eine bestimmte CPU-Architektur abzuzielen.
Beispielsweise:
Beachten Sie, dass diese Lösung leider auch nicht ultra-portabel ist, da sie von compilerspezifischen Definitionen abhängt (es gibt keinen Standard, aber hier ist eine schöne Zusammenstellung solcher Definitionen).
quelle
Versuche dies:
quelle
Bitte beachten Sie, dass die meisten Antworten hier nicht portierbar sind, da Compiler diese Antworten heute in der Kompilierungszeit auswerten (abhängig von der Optimierung) und einen bestimmten Wert basierend auf einer bestimmten Endianness zurückgeben, während die tatsächliche Maschinenendianness abweichen kann. Die Werte, auf denen die Endianness getestet wird, erreichen niemals den Systemspeicher, sodass der tatsächlich ausgeführte Code unabhängig von der tatsächlichen Endianness das gleiche Ergebnis zurückgibt.
Zum Beispiel , in ARM Cortex-M3 wird das implementierte endianness in einer Status - Bit AIRCR.ENDIANNESS reflektieren und Compiler diesen Wert in der Kompilierung nicht wissen können.
Kompilierungsausgabe für einige der hier vorgeschlagenen Antworten:
https://godbolt.org/z/GJGNE2 für diese Antwort,
https://godbolt.org/z/Yv-pyJ für diese Antwort und so weiter.
Um es zu lösen, müssen Sie das
volatile
Qualifikationsmerkmal verwenden.Yogeesh H T
Die Antwort ist die nächstgelegene für den heutigen Gebrauch im wirklichen Leben. DaChristoph
jedoch eine umfassendere Lösung vorgeschlagen wird, würde eine geringfügige Korrektur seiner Antwort die Antwort vervollständigen. Fügen Sie einfachvolatile
die Gewerkschaftserklärung hinzu :static const volatile union
.Dies würde das Speichern und Lesen aus dem Speicher sicherstellen, was zur Bestimmung der Endianness erforderlich ist.
quelle
Wenn Sie den Präprozessor #defines sichern
Normalerweise finden Sie Dinge, die Ihnen helfen. Mit Kompilierzeitlogik.
Verschiedene Compiler können jedoch unterschiedliche Definitionen haben.
quelle
Meine Antwort ist nicht wie gefragt, aber es ist wirklich einfach zu finden, ob Ihr System Little Endian oder Big Endian ist?
Code:
quelle
C Code zur Überprüfung, ob ein System Little-Endian oder Big-Indian ist.
quelle
Makro, um Endiannes zu finden
oder
quelle