web-dev-qa-db-ja.com

C#int to byte []

intbyte[]に変換する必要があります。それを行う1つの方法は、BitConverter.GetBytes()を使用することです。ただし、それが次の仕様に一致するかどうかは不明です。

XDR符号付き整数は、範囲[-2147483648,2147483647]の整数をエンコードする32ビットのデータです。整数は2の補数表記で表されます。最上位バイトと最下位バイトはそれぞれ0と3です。整数は次のように宣言されます。

ソース:RFC1014 3.2

上記の仕様を満たすintからバイトへの変換を行うにはどうすればよいですか?

153
Peter

RFCは、符号付き整数は、バイトがビッグエンディアン方式で並べられた通常の4バイト整数であると言っているところです。

さて、あなたはおそらくリトルエンディアンのマシンで作業しており、BitConverter.GetBytes()byte[]を逆にしてくれます。だからあなたは試すことができます:

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
Array.Reverse(intBytes);
byte[] result = intBytes;

ただし、コードを最も移植性の高いものにするには、次のようにします。

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
if (BitConverter.IsLittleEndian)
    Array.Reverse(intBytes);
byte[] result = intBytes;
201
paracycle

これを行う別の方法があります。1xバイト= 8xビットを知っているので、「通常の」整数(int32)には32ビット(4バイト)が含まれています。 >>演算子を使用してビットを右にシフトできます(>>演算子は値を変更しません。)

int intValue = 566;

byte[] bytes = new byte[4];

bytes[0] = (byte)(intValue >> 24);
bytes[1] = (byte)(intValue >> 16);
bytes[2] = (byte)(intValue >> 8);
bytes[3] = (byte)intValue;

Console.WriteLine("{0} breaks down to : {1} {2} {3} {4}",
    intValue, bytes[0], bytes[1], bytes[2], bytes[3]);
34
Maciek

BitConverter.GetBytes(int)は、エンディアンネスが間違っていることを除いて、ほとんどあなたが望むことをします。

IPAddress.HostToNetwork メソッドを使用して、BitConverter.GetBytesを使用する前に整数値内のバイトをスワップするか、Jon Skeetの EndianBitConverterクラス を使用できます。両方のメソッドは、移植性に関して正しいことを行います。

int value;
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));
22
dtb

この説明を見ると、このxdr整数は単なるビッグエンディアンの「標準」整数であると感じていますが、最も難読化された方法で表現されています。 2の補数表記 はU2として知られ、今日のプロセッサで使用しているものです。バイト順は、それが ビッグエンディアン 表記であることを示しています。
そのため、質問に答えるには、配列の要素をリトルエンディアンでエンコードする必要があります(0 <-> 3、1 <-> 2)。念のため、まずBitConverter.IsLittleEndianをチェックして、実行中のマシンを確認する必要があります。

3
Marcin Deptuła

Two's Complementを含む数を表すさまざまな方法に関するより一般的な情報が必要な場合は、以下を参照してください。

Two's Complement および Signed Number Representation ウィキペディア

2
Eric J.

上記のサンプルのすべてのコードがなぜ...

明示的なレイアウトを持つ構造体は両方の方法で機能し、パフォーマンスに影響はありません。

更新:エンディアンに対処する方法についての質問があるので、それを抽象化する方法を示すインターフェイスを追加しました。別の実装構造体は反対のケースに対処できます

public interface IIntToByte
{
    Int32 Int { get; set;}

    byte B0 { get; }
    byte B1 { get; }
    byte B2 { get; }
    byte B3 { get; }
}

[StructLayout(LayoutKind.Explicit)]
public struct IntToByteLE : UserQuery.IIntToByte
{
    [FieldOffset(0)]
    public Int32 IntVal;

    [FieldOffset(0)]
    public byte b0;
    [FieldOffset(1)]
    public byte b1;
    [FieldOffset(2)]
    public byte b2;
    [FieldOffset(3)]
    public byte b3;

    public Int32 Int {
        get{ return IntVal; }
        set{ IntVal = value;}
    }

    public byte B0 => b0;
    public byte B1 => b0;
    public byte B2 => b0;
    public byte B3 => b0; 
}
0
Sten Petrov