Gibt es eine Möglichkeit zu erzwingen, bestimmte endianness für eine C-oder C++ - struct?
Ich gesehen habe ein paar Fragen und Antworten in Bezug auf die endianness der Strukturen, aber Sie waren zu erkennen, die endianness des Systems, oder die Umwandlung von Daten zwischen den zwei verschiedenen endianness.
Was möchte ich nun, allerdings, wenn es eine Weise zu erzwingen, bestimmte endianness ein gegebenes struct. Gibt es einige gute compiler-Direktiven oder andere einfache Lösungen neben umschreiben die ganze Sache aus einer Menge von Makros Bearbeiten auf bitfields?
Eine Allgemeine Lösung wäre schön, aber ich würde gerne mit einer bestimmten gcc-Lösung als gut.
Edit:
Danke für all die Kommentare, die zeigen, warum es nicht eine gute Idee durchzusetzen, endianness, aber in meinem Fall ist genau das, was ich brauche.
Einer großen Menge von Daten generiert wird, die durch einen spezifischen Prozessor (der wird sich nie ändern, ist es ein eingebettetes system mit einem benutzerdefinierten hardware), und es ist zu Lesen von einem Programm (welches ich auf Arbeit bin) läuft auf einem unbekannten Prozessor. Byte-Weise Auswertung der Daten wäre schrecklich lästig, weil es besteht aus Hunderten von verschiedenen Arten von Strukturen, die riesige und Tiefe: die meisten von Ihnen haben viele Schichten von anderen großen Strukturen im inneren.
Änderung der software für die embedded-Prozessor ist aus der Frage. Die Quelle ist vorhanden, dieser ist der Grund, warum ich vorhabe zu verwenden, die Strukturen dieses Systems, anstatt von vorne anfangen und Bewertung aller Daten byte-Weise.
Dies ist der Grund, warum ich erzählen muss, der compiler, die endianness es verwenden sollten, ist es egal, wie effizient oder nicht, wird es werden.
Es nicht sein, real änderung in der endianness. Auch wenn es nur eine Schnittstelle, und körperlich alles verarbeitet wird, in der eigenen Prozessoren endianness, es ist durchaus akzeptabel für mich.
- Ich kann nicht sehen, den Punkt von diesem? Die einzige Zeit, die Sie kümmern wird, wenn marshalling und unmarshalling der Daten - alle anderen Instanzen, werden Sie wollen, dass die Plattform-spezifische endian Typ - warum also Kraft einer komplizierten Konvertierung System für alle Anwendungen einer bestimmten Struktur? Warum nicht isolieren, es rein um das marshalling/unmarshalling-bits?
- Endian ist nicht eine Eigenschaft der Struktur ist, sondern eine Eigenschaft der Architektur, dass ist der code ausgeführt wird. Zwar könnte Sie theoretisch zwingen, die in-memory-Repräsentation eines bestimmten endian Typ, das würde Kraft Konvertierungen von Plattform zu struct endian Typ in alle lese-und Schreibzugriffe auf jedes Feld, für etwas, das beobachten von außen. Sie sollten nur Formate zu konvertieren, wenn der Umgang mit der Außenwelt.
- Ich Las eine Menge von Daten aus einem embedded system, welches Hunderte von unterschiedlichen Strukturen, viele von Ihnen mit tiefen Schichten der andere große Strukturen im inneren. Als ich die Quelle der embedded Systems habe ich den code der all diese Strukturen. Dies ist der Grund, warum es viel einfacher wäre, einfach einzusetzen, da das Lesen und auswerten der Daten byte-Weise, würde sehr lange dauern. Die Größe der Daten und die Anzahl der unterschiedlichen Strukturen ist riesig, so dass selbst die Konvertierung ist besser zu vermeiden.
- Ich beschäftige mich mit der Außenwelt. Ich weiß, die Durchsetzung endian ist nicht die sauberste Sache zu tun, aber in diesem speziellen Fall mit dieser speziellen hardware-das ist genau das was ich brauche.
- wo kommt dein code ausgeführt werden? Auf dem gleichen Prozessor oder außerhalb? Wenn es auf der gleichen Prozessor - Sie müssen nicht zu kümmern, wenn Sie außerhalb der Mechanismus der übertragung der Daten vom embedded system zu verkaufen, sollte Angebot mit der Umbauten... Und vor Ort arbeiten Sie in das format von dem Prozessor, wo man den code auszuführen...
- Nein, mein code läuft nicht auf den selben Prozessor, das ist, warum ich möchte, um die Durchsetzung der endianness, weil ich weiß, dass die endianness der Prozessor die Daten, und dass der Prozessor wird sich nicht ändern, weil es ein embedded-system läuft auf einer ganz bestimmten hardware. Eigentlich ist der Prozessor, der erstellt die Daten die man nie ändern wird, aber der Prozessor, wo mein code läuft, wird sich möglicherweise ändern.
- Und damit alle Ihre "business-Logik" funktionieren muss in den endian Typ der lokale Prozessor - jetzt vorstellen, müssen Sie die folgenden Operationen
some_struct.int_value += 10
- Sie hätte mit der Umsetzung einiger Hack pokery, um die Arbeit in einem bestimmten endian Typ, wenn Ihr Prozessor nicht passen. Nun Stell dir vor, dies zu tun überall in Ihrem code - es werde ein furchtbares Durcheinander. Wenn Sie wirklich besorgt über die Leistung, diese Adresse in Ihrem marshalling/unmarhsalling code... - Ich glaube nicht, dass Sie verstehen, was Nim zu sagen versucht. Sie können die Schnittstelle der Anwendung, die den embedded-Prozessor, und das ist in Ordnung, aber das bedeutet nur, dass, wenn Ihre Anwendung interagiert mit diesem Prozessor wird es zu übersetzen aus Ihrer internen Repräsentation, die der Prozessor. Für alle die internen Darstellungen, die Sie verwenden sollten, unabhängig von der nativen Plattform-Logik hat, und einfach serialisieren und Deserialisieren in die Schnittstelle.
- genau, die Serialisierung ist das problem. Der code auf dem embedded-Prozessor nicht verändert werden kann, und was es tut, ist einfach dumping alles mit memcpy in char-arrays. Nachdem die Quelle der es heißt nur, dass ich zumindest nicht haben, um das reverse-Engineering Ihrer Struktur, nicht aber, dass ich in der Lage bin (oder darf) in irgendeiner Weise zu verändern.
- Ok, zurück zu den Grundlagen: Sie nicht möchten, ändern Sie den endian Typ in deinem Prozessor, der Sie nur möchten in der Lage sein zu leihen, die Strukturen, die in die anderen Prozessoren endianness und übersetzen Sie Sie. Das heißt Serialisierung und es ist ganz anders aus, was deine Frage fragt nach. Für die, die Sie brauchen, um zu definieren, die stuctures, Lesen von der Netzwerk - /Datenträger und wenden Sie die endianness-Konvertierung einmal beim Lesen, verwenden Sie dann in der aktuellen Prozessor-format und konvertieren einmal beim zurückschreiben auf die Festplatte/Netzwerk. Für die gesamte Zeit, in Erinnerung wird es dem lokalen endian Typ.
- Deine Frage sollte so etwas in der Art von ich-Prozessor X mit endian Typ Y aus, die ich Lesen möchte eine Reihe von Strukturen und der Arbeit mit Ihnen. Wie kann ich ausführen, dass die Umstellung? Anstatt ich will zur Durchsetzung einer bestimmten endian Typ in meine Strukturen.
- Ich weiß, was Serialisierung bedeutet, und ich es mich in der Vergangenheit. Allerdings gibt es Probleme mit ihm in diesem Fall: habe ich nicht einen schönen Serialisierung auf der Senderseite, die kann ich bequem de-serialisieren, die auf der empfangenden Seite. Die Probleme mit der Konvertierung der Daten ist, dass es ist riesig und vielfältig. Eine Struktur, die eine andere Struktur im inneren, die arrays unterschiedlicher Strukturen, die jeweils anderen arrays, Variablen und Strukturen im inneren, und so weiter, mit arrays und Variablen in verschiedenen Größen, die alle um. Schreiben Sie eine Konvertierungs-Werkzeug für die Sache nehmen würde, sehr viel Zeit.
- Es spielt keine Rolle, wenn es nicht eine echte ändern Sie in der endianness. Auch wenn es nur eine Schnittstelle und die echten Daten physisch abgespeichert, wobei die Prozessoren eigene endianness, es wäre eine Lösung.
- Gute Frage. Manchmal wäre es sehr schön, um ein Attribut für die Angabe von endian für Strukturen und Mitglieder. So etwas wie:
__attribute__ ((endianness (BIG_ENDIAN)))
für den gcc. Viele Netzwerk-Protokolle verwendet bigendian (=network-byteorder). Also-Protokoll Quellen haben vielentohs()
,htonl()
usw. fordert, was Konvertierungen. Wenn es die bit-Felder in Strukturen, dann wird der code noch hässlich (Siehestruct ip
von "netinet/ip.h").
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Weg, den ich in der Regel behandeln diese lautet in etwa so:
Ebenso für
be_uint32_t
.Dann definieren Sie eine Struktur wie diese:
Der Punkt ist, dass der compiler wird mit ziemlicher Sicherheit das Layout der Felder in der Reihenfolge, die Sie schreiben, damit Sie sind wirklich besorgt ist big-endian-Integer. Die
be_uint16_t
Objekt ist eine Klasse, die weiß, wie zu konvertieren, sich transparent zwischen big-endian und Maschine-endian-als erforderlich. Wie diese:In der Tat, wenn Sie kompilieren Sie das snippet mit jeder halbwegs gute C++ - compiler sollten Sie finden, es gibt ein big-endian "13" als eine Konstante.
Mit diesen Objekten, die in-memory-Repräsentation ist big-endian. So können Sie arrays erstellen, geben Sie in Strukturen, etc. Aber wenn Sie gehen, um mit Ihnen arbeiten, Sie magisch cast zu-Maschine-endian. Dies ist normalerweise eine einzelne Anweisung auf der x86 -, so ist es sehr effizient. Es gibt wenige Kontexte, wo Sie von hand gegossen:
...aber für die meisten-code können Sie benutzen Sie einfach als wären Sie built-in-Typen.
Ein bisschen spät, um der Partei, aber mit dem aktuellen GCC (getestet auf 6.2.1 wo es funktioniert und 4.9.2, wo es nicht implementiert) es ist endlich ein Weg, zu erklären, dass eine Struktur, die gehalten werden sollten in X-endian-byte-Reihenfolge.
Folgende test-Programm:
erstellt eine Datei "aus.bin", die Sie überprüfen können, mit einem hex-editor (z.B. hexdump -C aus.bin). Wenn die scalar_storage_order Attribut ist suppported darin enthalten sind auch die erwarteten 0xaabbff0000aaabcdefaabbccddee in dieser Reihenfolge und ohne Löcher. Leider ist dies natürlich sehr compiler-spezifisch.
Nein, ich denke nicht so.
Endian ist das Attribut des Prozessors, der angibt, ob ganze zahlen vertreten sind, von Links nach rechts oder von rechts nach Links, es ist nicht ein Attribut des Compilers.
Die besten Sie tun können, ist code schreiben, welches unabhängig von jeder byte-Reihenfolge.
Nein, es gibt keine solche Funktion. Wenn es existierte, könnte Compilern zu erzeugen übermäßige/ineffizienten code, also C++ nur nicht unterstützt.
Den üblichen C++ - Umgang mit der Serialisierung (was ich davon ausgehen ist, was Sie versuchen zu lösen) dies ist, lassen Sie die Struktur, die im Gedächtnis bleiben, in die genaue gewünschte layout und tun die Serialisierung in einer Weise, die endianness beibehalten wird bei der Deserialisierung.
Ich bin nicht sicher, ob die folgende geändert werden kann, für Ihre Zwecke anpassen, aber wo ich arbeite, haben wir Folgendes gefunden, um sehr nützlich sein in vielen Fällen.
Wenn endianness ist wichtig, wir verwenden zwei verschiedene Datenstrukturen. Man ist gemacht, um darzustellen, wie es erwartet, um anzukommen. Die andere ist, wie wollen wir es vertreten zu sein, in Erinnerung. Konvertierungs-Routinen werden dann entwickelt, um zwischen den beiden wechseln.
Den workflow arbeitet so ...
Finden wir diese Entkopplung nützlich, weil (aber nicht beschränkt auf) ...
Hoffentlich diese Entkopplung kann nützlich sein, um Ihre Anwendung zu.
Einen möglichen innovativen Lösung wäre die Verwendung von einem C-interpreter wie
Ch
und Kraft, die endian-Codierung zu groß.Boost liefert endian-Puffer für diese.
Beispiel:
Vielleicht keine direkte Antwort, aber mit dem Lesen durch diese Frage hoffentlich beantworten einige Ihrer Anliegen.
Können Sie die Struktur einer Klasse mit Getter und setter für die Daten der Mitglieder. Die Getter und setter implementiert, mit so etwas wie:
Tun wir dies manchmal, wenn wir beim Lesen einer Struktur in eine Datei - Lesen wir es in ein struct, und verwenden Sie diese sowohl big-endian und little-endian-Maschinen Zugriff auf die Daten ordnungsgemäß.
Es ist eine Darstellung der Daten für diese genannt XDR. Haben Sie einen Blick auf es.
http://en.wikipedia.org/wiki/External_Data_Representation
Obwohl es vielleicht ein wenig zu viel für Ihr Embedded System. Versuchen Sie eine Suche für eine bereits implementierte Bibliothek, die Sie verwenden können (überprüfen Sie Lizenz-Einschränkungen!).
XDR ist in der Regel in Netzwerk-Systeme, da Sie benötigen eine Möglichkeit zum verschieben von Daten in eine Endianness unabhängige Weise. Obwohl Sie nichts sagt, dass es nicht verwendet werden, außerhalb von Netzwerken.