Ich muss eine int
in eine byte[]
einzige Möglichkeit umwandeln , es zu verwenden BitConverter.GetBytes()
. Aber ich bin mir nicht sicher, ob das der folgenden Spezifikation entspricht:
Eine XDR-Ganzzahl mit Vorzeichen ist ein 32-Bit-Datum, das eine Ganzzahl im Bereich [-2147483648,2147483647] codiert. Die Ganzzahl wird in Zweierkomplementnotation dargestellt. Die höchst- und niedrigstwertigen Bytes sind 0 bzw. 3. Ganzzahlen werden wie folgt deklariert:
Quelle: RFC1014 3.2
Wie könnte ich eine Int-zu-Byte-Transformation durchführen, die die obige Spezifikation erfüllt?
c#
.net
bit-manipulation
nfs
Peter
quelle
quelle
Antworten:
Der RFC versucht nur zu sagen, dass eine vorzeichenbehaftete Ganzzahl eine normale 4-Byte-Ganzzahl ist, deren Bytes auf Big-Endian-Weise geordnet sind.
Jetzt arbeiten Sie höchstwahrscheinlich an einer Little-Endian-Maschine und
BitConverter.GetBytes()
geben Ihnen dasbyte[]
Gegenteil. Sie könnten also versuchen:Damit der Code am portabelsten ist, können Sie dies folgendermaßen tun:
quelle
byte[] result = intBytes;
? ist nichtintBytes
schon das Array, das Sie wollen?result
ist in diesem Codestück überflüssig. Ich fand es jedoch pädagogischer, dem Leser explizit zu zeigen, was das Ergebnis war, als anzunehmen, dass er herausfinden kann, dass das Ergebnis in einer Variablen mit dem Namen enthalten istintBytes
. Außerdem ist die Zuweisung billig, da weder der Speicher kopiert noch neuer Speicher zugewiesen wird, sondern lediglich dem bereits zugewiesenen Array ein neuer Name hinzugefügt wird. Warum also nicht?Hier ist eine andere Möglichkeit: Wie wir alle wissen, enthält 1x Byte = 8x Bits und eine "reguläre" Ganzzahl (int32) enthält 32 Bits (4 Bytes). Wir können den Operator >> verwenden, um die Bits nach rechts zu verschieben (der Operator >> ändert den Wert nicht.)
quelle
& 0xFF
Bits sind nicht erforderlich.unchecked
Block einschließen. Derzeit funktioniert es nur, wenn die Überprüfung des Ganzzahlüberlaufs in den Compilereinstellungen deaktiviert ist.BitConverter.GetBytes(int)
macht fast was du willst, außer dass die Endianness falsch ist.Sie können die IPAddress.HostToNetwork- Methode verwenden, um die Bytes innerhalb des Integer-Werts auszutauschen, bevor Sie
BitConverter.GetBytes
die EndianBitConverter-Klasse von Jon Skeet verwenden oder verwenden . Beide Methoden machen das Richtige (tm) in Bezug auf die Portabilität.quelle
Wenn ich mir diese Beschreibung ansehe, habe ich das Gefühl, dass diese xdr-Ganzzahl nur eine Big-Endian-Ganzzahl ist, aber auf die verschleierteste Weise ausgedrückt wird. Die Komplementnotation von Two ist besser als U2 bekannt und wird auf heutigen Prozessoren verwendet. Die Bytereihenfolge gibt an, dass es sich um eine Big-Endian- Notation handelt.
Wenn Sie Ihre Frage beantworten, sollten Sie die Elemente in Ihrem Array (0 <--> 3, 1 <--> 2) umkehren, da sie in Little-Endian codiert sind. Um sicherzugehen, sollten Sie zuerst überprüfen
BitConverter.IsLittleEndian
, auf welchem Computer Sie ausgeführt werden.quelle
Warum all dieser Code in den obigen Beispielen ...
Eine Struktur mit explizitem Layout verhält sich in beide Richtungen und hat keinen Leistungseinbruch.
Update: Da es eine Frage zum Umgang mit Endianness gibt, habe ich eine Schnittstelle hinzugefügt, die zeigt, wie man das abstrahiert. Eine andere Implementierungsstruktur kann den umgekehrten Fall behandeln
quelle
Wenn Sie allgemeinere Informationen zu verschiedenen Methoden zur Darstellung von Zahlen, einschließlich Two's Complement, wünschen, schauen Sie sich Folgendes an:
Two's Complement und Signed Number Representation auf Wikipedia
quelle
Die andere Möglichkeit besteht darin, BinaryPrimitives wie folgt zu verwenden
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
quelle
quelle
quelle
Int16
.