2009-08-23 15 views
128

Muszę przekonwertować int na byte[] jednym ze sposobów na to jest użycie BitConverter.GetBytes(). Ale im pewien jeśli odpowiada następującej specyfikacji:C# int na bajt []

XDR ze znakiem jest układ odniesienia 32-bitowy, który koduje całkowitą w zakresie [-2147483648,2147483647]. Liczba całkowita jest reprezentowana w notacji uzupełnienia dwójki. Najbardziej i najmniej znaczące bajty to odpowiednio: 0 i 3. Całkowitymi są zadeklarowane w następujący sposób:

Źródło: RFC1014 3.2

Jak mogę zrobić int do transformacji bajtów, które spełniają powyższą specyfikację?

+0

To jest dobre pytanie. – ChaosPandion

Odpowiedz

168

RFC próbuje jedynie powiedzieć, że liczba całkowita ze znakiem jest normalną 4-bajtową liczbą całkowitą z bajtami uporządkowanymi w sposób big-endian.

Teraz najprawdopodobniej pracujesz na maszynie Little-Endian, a BitConverter.GetBytes() da ci odwrócony numer byte[]. Więc można spróbować:

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

Dla kodu za najbardziej przenośny, jednak można to zrobić tak:

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

Lub użyj funkcji ToArray. bajt [] result = BitConverter.GetBytes (intValue) .Reverse(). ToArray(); –

19

BitConverter.GetBytes(int) prawie robi to, co chcesz, z wyjątkiem endianowości jest źle.

Możesz użyć metody IPAddress.HostToNetwork, aby zamienić bajty w obrębie wartości całkowitych przed użyciem BitConverter.GetBytes lub użyć EndianBitConverter class Jona Skeeta. Obie metody działają prawidłowo (tm) w odniesieniu do przenośności.

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

Kiedy patrzę na tego opisu, mam wrażenie, że to całkowita XDR jest tylko big-endian „standard” całkowitą, ale jest wyrażona w sposób najbardziej ukrywane. Two's complement notation jest lepiej znany jako U2, i to jest to, czego używamy na dzisiejszych procesorach. Kolejność bajtów wskazuje, że jest to notacja big-endian.
Odpowiadając na twoje pytanie, powinieneś odwrócić elementy w swojej tablicy (0 < -> 3, 1 < -> 2), ponieważ są one zakodowane w little-endian. Aby się upewnić, najpierw sprawdź numer BitConverter.IsLittleEndian, aby zobaczyć, na której maszynie aktualnie pracujesz.

30

Oto kolejny sposób, aby to zrobić: jak wszyscy wiemy 1x bajt = 8x bitów, a także "zwykła" liczba całkowita (int32) zawiera 32 bity (4 bajty). Możemy użyć operatora >> przesunięcie bitów w prawo (>> operator nie zmienia wartości.)

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]); 
+0

Inicjatory tablic i bitów xor (^) i '& 0xFF' są niepotrzebne. – dtb

+0

Tak, ale chciałem tylko pokazać, jak to działa – Maciek

+5

To jest big-endian, więc MSB jest przechowywany jako pierwszy, więc powinieneś odwrócić swoje indeksy. –

0
byte[] Take_Byte_Arr_From_Int(Int64 Source_Num) 
{ 
    Int64 Int64_Num = Source_Num; 
    byte Byte_Num; 
    byte[] Byte_Arr = new byte[8]; 
    for (int i = 0; i < 8; i++) 
    { 
     if (Source_Num > 255) 
     { 
     Int64_Num = Source_Num/256; 
     Byte_Num = (byte)(Source_Num - Int64_Num * 256); 
     } 
     else 
     { 
     Byte_Num = (byte)Int64_Num; 
     Int64_Num = 0; 
     } 
     Byte_Arr[i] = Byte_Num; 
     Source_Num = Int64_Num; 
    } 
    return (Byte_Arr); 
} 
+0

proszę dodać więcej wyjaśnień –

+0

Dzięki za odpowiedź, dlaczego zdecydowałeś się napisać nową implementację zamiast korzystania z https://stackoverflow.com/a/1318948/58553? (czy są jakieś pro lub przeciwsobne rozwiązania) – Peter

+0

W przypadku, gdy projekt musi zostać opracowany przy użyciu nie tylko jednego języka, przydatne może być uświadomienie sobie podobieństwa kodu między językami w sytuacji, gdy konieczne jest wprowadzenie identycznych pomysłów. W ten sposób może pomóc w złapaniu błędów. Z pewnością za pomocą funkcji "C#" "BitConverter.GetBytes" z "Endian" sprawdzanie, że wszystko, co potrzebne w większości przypadków. Co więcej, w pewnej sytuacji może się zdarzyć, że użyjesz konwersji nie tylko do Int32 (4 bajty) lub Int64 (8 bajtów), ale do innej liczby bajtów. Dzięki. –

-1

Dlaczego cały ten kod w powyższych próbek ...

struct z wyraźną układ działa w obie strony i nie ma wydajność hit

[StructLayout(LayoutKind.Explicit)] 
struct IntByte 
{ 
    [FieldOffset(0)] 
    public int IntVal; 

    [FieldOffset(0)] 
    public byte B0; 
    [FieldOffset(1)] 
    public byte B1; 
    [FieldOffset(2)] 
    public byte B2; 
    [FieldOffset(3)] 
    public byte B3; 
} 
+0

Jak byś tego użył? a po drugie, czy uzyskasz taki sam wynik, nawet jeśli używasz tego na "big-endian" i "little-endian". – Peter

Powiązane problemy