Inverser l'ordre des octets dans .NET
Dans le code ci-dessous, pourquoi faire X et Y prendre différentes valeurs que ce que je pense intuitivement?
Si les octets 0 à 7 sont écrites dans la mémoire tampon, ne faut-il pas la résultante de temps avez-octets dans le même ordre? C'est comme la lecture de la longue valeurs dans l'ordre inverse.
x 0x0706050403020100 long
y 0x0706050403020100 long
z 0x0001020304050607 long
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
ms.Write(buffer, 0, buffer.Length);
ms.Flush();
ms.Position = 0;
BinaryReader reader = new BinaryReader(ms);
long x = reader.ReadInt64();
long y = BitConverter.ToInt64(buffer, 0);
long z = BitConverter.ToInt64(buffer.Reverse<byte>().ToArray<byte>(), 0);
byte[] xbytes = BitConverter.GetBytes(x);
byte[] ybytes = BitConverter.GetBytes(y);
byte[] zbytes = BitConverter.GetBytes(z);
(Je ne sais pas quoi balise à cette question, au-delà de juste .NET.)
BitConverter.IsLittleEndian
est faux. Si mon ordinateur est en big endian, pourquoi est-ce arrivé?
- C'est un Windows 7 64-bit machine
- Intel core 2 Quad Q9400 2.66 GHz LGA 775 95W Quad-Core, Modèle de Processeur BX80580Q9400
- SUPERMICRO MBD-C2SBX+-O LGA 775 Intel X48 ATX la carte Mère Intel
Les résultats de ce code (en réponse à Jason commentaire):
byte[] buffer = new byte[] { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
long y = BitConverter.ToInt64(buffer, 1);
Console.WriteLine(BitConverter.IsLittleEndian);
Console.WriteLine(y);
Résultat:
False
506097522914230528
source d'informationauteur Amy
Vous devez vous connecter pour publier un commentaire.
BinaryReader.ReadInt64
est little endian par la conception. À partir de la documentation:En fait, nous pouvons inspecter la source pour
BinaryReader.ReadInt64
l'aide d'un Réflecteur.Montrant que
BinaryReader.ReadInt64
se lit comme little endian indépendant de la sous-tendent l'architecture de la machine.Maintenant,
BitConverter.ToInt64
est supposé à l'égard de l'endianness de votre sous-jacente de la machine. Dans le Réflecteur, nous pouvons voirDonc ce que nous voyons ici, c'est que si
startIndex
est congru à zéro modulo huit direct en fonte est faite à partir de huit octets commençant à l'adressenumRef
. Ce cas est traité spécialement en raison de problèmes d'alignement. La ligne de codese traduit directement
Nous voyons donc que, dans ce cas, la clé est la
ldind.i8
instruction. La CLI est agnostique sur le boutisme de la sous-jacentes de la machine. Il permet au compilateur JIT de gérer cette question. Sur un little-endian machine,ldind.i8
charge supérieur adresses dans plus de bits significatifs et sur un big-endian machineldind.i8
charge plus élevée des adresses en moins importante octets. Par conséquent, dans ce cas, endianness est manipulé correctement.Dans les autres cas, vous pouvez voir qu'il y a une vérification explicite de la propriété statique
BitConverter.IsLittleEndian
. Dans le cas de little endian la mémoire tampon est interprété comme little endian (de sorte que la mémoire{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }
est interprété comme le long0x0706050403020100
) et dans le cas de big endian la mémoire tampon est interprété comme big endian (de sorte que la mémoire{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }
est interprété comme le long0x0001020304050607
). Donc, pourBitConverter
il s'agit de l'endianness de la underyling de la machine. Je remarque que vous êtes sur une puce Intel sous Windows 7 x64. Puces Intel little-endian. Je note que dans le Réflecteur, le constructeur statique pourBitConverter
est définie comme suit:C'est sur mon Windows Vista x64-linge. (Cela peut varier, par exemple .NET CF sur une XBox 360.) Il n'y a aucune raison pour Windows 7 x64 pour être différent. Par conséquent, vous êtes sûr que
BitConverter.IsLittleEndian
estfalse
? Il devrait êtretrue
et, par conséquent, le comportement que vous voyez est correct.Vous êtes sur un little endian de la machine, où les entiers sont stockés octet le moins significatif en premier.
BinaryReader suppose Little Endian ordre: http://msdn.microsoft.com/en-us/library/system.io.binaryreader.readint64.aspx
Êtes-vous tout à fait sûr que BitConverter.IsLittleEndian est de retour faux?
Si vous inspectez à travers le débogueur-regarder avant vous avez utilisé l'un de ses méthodes que vous pourriez obtenir de faux, même si elle doit renvoyer true.
Lecture de la valeur par le biais du code pour être tout à fait certain.
Voir aussi IsLittleEndian champ des rapports faux, mais il doit être Little-Endian?
Si vous vous souciez de la endian-ness de votre octets, Jon Skeet écrit une classe pour vous permettre de choisir le endian-commande lorsque vous effectuez la conversion.
Voir C# little endian ou big endian?
C'est juste:
BitConverter
utilise le stockage de la machine sur laquelle il tourne. Pour assurer un big-endian numéro, utilisezIPAddress.HostToNetworkOrder
. Par exemple: