J'ai besoin de convertir un int
en une byte[]
seule façon de le faire est d'utiliser BitConverter.GetBytes()
. Mais je ne sais pas si cela correspond à la spécification suivante:
Un entier signé XDR est une donnée 32 bits qui code un entier compris dans la plage [-2147483648,2147483647]. L'entier est représenté dans la notation du complément à deux. Les octets les plus et les moins significatifs sont respectivement 0 et 3. Les entiers sont déclarés comme suit:
La source: RFC1014 3.2
Comment puis-je effectuer une transformation int en octet qui satisferait la spécification ci-dessus?
c#
.net
bit-manipulation
nfs
Peter
la source
la source
Réponses:
La RFC essaie simplement de dire qu'un entier signé est un entier normal de 4 octets avec des octets ordonnés de manière big-endian.
Maintenant, vous travaillez très probablement sur une machine little-endian et
BitConverter.GetBytes()
vous donnerez l'byte[]
inverse. Vous pouvez donc essayer:Pour que le code soit le plus portable, cependant, vous pouvez le faire comme ceci:
la source
byte[] result = intBytes;
? n'est pasintBytes
déjà le tableau que vous voulez?result
est redondant dans ce morceau de code. Cependant, j'ai pensé qu'il était plus pédagogique de montrer explicitement au lecteur quel était le résultat que de supposer qu'il pouvait comprendre que le résultat est contenu dans une variable nomméeintBytes
. De plus, faire l'affectation est bon marché car il ne copie pas la mémoire ni n'alloue de nouvelle mémoire, il ajoute simplement un nouveau nom au tableau déjà alloué. alors pourquoi ne pas le faire?Voici une autre façon de le faire: comme nous le savons tous 1x octet = 8x bits et aussi, un entier "régulier" (int32) contient 32 bits (4 octets). Nous pouvons utiliser l'opérateur >> pour décaler les bits vers la droite (l'opérateur >> ne change pas la valeur.)
la source
& 0xFF
bits ne sont pas nécessaires.unchecked
bloc. Actuellement, cela ne fonctionne que si la vérification du dépassement d'entier est désactivée dans les paramètres du compilateur.BitConverter.GetBytes(int)
fait presque ce que vous voulez, sauf que l'endianisme est faux.Vous pouvez utiliser la méthode IPAddress.HostToNetwork pour permuter les octets dans la valeur entière avant d'utiliser
BitConverter.GetBytes
ou d'utiliser la classe EndianBitConverter de Jon Skeet . Les deux méthodes font la bonne chose (tm) en ce qui concerne la portabilité.la source
Quand je regarde cette description, j'ai le sentiment que cet entier xdr n'est qu'un entier "standard" big-endian, mais il est exprimé de la manière la plus obscure. La notation du complément de Two est mieux connue sous le nom de U2, et c'est ce que nous utilisons sur les processeurs d'aujourd'hui. L'ordre des octets indique qu'il s'agit d'une notation big-endian .
Donc, pour répondre à votre question, vous devez inverser les éléments de votre tableau (0 <--> 3, 1 <--> 2), car ils sont encodés en petit-boutiste. Juste pour être sûr, vous devez d'abord vérifier
BitConverter.IsLittleEndian
sur quelle machine vous utilisez.la source
Pourquoi tout ce code dans les exemples ci-dessus ...
Une structure avec une disposition explicite agit dans les deux sens et n'a aucun impact sur les performances.
Mise à jour: Puisqu'il y a une question sur la façon de gérer l'endianness, j'ai ajouté une interface qui illustre comment résumer cela. Une autre structure d'implémentation peut gérer le cas contraire
la source
Si vous souhaitez des informations plus générales sur les différentes méthodes de représentation des nombres, y compris le complément à deux, consultez:
Complément à deux et représentation des nombres signés sur Wikipedia
la source
L'autre façon est d'utiliser BinaryPrimitives comme ceci
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
la source
la source
la source
Int16
.