2016-12-19 12 views
2

バイト配列(4バイトごとに1つのInt32)で表されるInt32の配列があり、Int32配列(Byteの長さ)に変換したい。長さ/ 4)。ここ は私が何をしたいの例です:バイト配列で表されるInt32配列をC言語でInt32配列に変換する方法

//byte[] buffer; 
for (int i=0; i<buffer.Length; i+=4) 
{ 
    Int32 temp0 = BitConverter.ToInt32(buffer, i); 
    temp0 += 10; 
    byte[] temp1 = BitConverter.GetBytes(temp0); 
    for (int j=0;j<4;j++) 
    { 
     buffer[i + j] = temp1[j]; 
    } 
} 

しかし、私はそれらをコピーしたくない、私はちょうど(のためにそれがのInt32列ではなくバイト配列でコンパイラに伝えることができるようにしたいです後の操作)。

私はこのHow to Convert a byte array into an int arrayを見ましたが、すべてのバイトをInt32に変換し、すべてバイトをInt32に変換します。 私はこれを他の配列にコピーしてパフォーマンスを向上させないといけません。

(ハードウェアはエンディアンネイティブで、リトルエンディアンのリトルエンディアンシステムと見なすことができます)。

+2

は安全でないものとポインタの仕事のように聞こえます – pm100

+0

[Here](https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,1618fc20415532f2)は[BitConverter.ToInt32(byte [ ]、Int32) '](https://msdn.microsoft.com/en-us/library/system.bitconverter.toint32(v = vs.110).aspx)。このコードは 'fixed(byte * pbyte =&value [startIndex]){if(startIndex%4 == 0){//データがアライメントされて返されます*((int *)pbyte); } 'は、整列されたときにint32に4バイトを単純にキャストすることを意味します。変換しないため、高速である必要があります。誰かが確認できますか? – Quantic

+0

@ pm100あなたは安全でないコードを書いてください。私は試してみましたが、私はすべての種類のエラーがあります:( – pio

答えて

3

コピーせずに直接変換する方法はありません。あなたは整数としてバイトを返すためにlinqクエリを書くことができますが、それを操作することはできません。あなたのbyte配列から、あなたがint値を読み取ることができます

public class IntArrayOverBytes 
{ 
    private readonly byte[] bytes; 
    public IntArrayOverBytes(byte[] bytes) 
    { 
     this.bytes = bytes; 
    } 

    public int this[int index] 
    { 
     get { return BitConverter.ToInt32(bytes, index * 4); } 
     set { Array.Copy(BitConverter.GetBytes(value), 0, bytes, index * 4, 4); } 
    } 
} 

このクラスでは、それらをライトバック:

IntArrayOverBytes intArray = new IntArrayOverBytes(bytes); 
intArray[5] = 2016; 
Console.WriteLine(intArray[5]); 

一つの方法は、自分のクラスでこれをラップすることができるものあなたが望む達成するために

Arrayのような機能の場合は、さらにコードを追加する必要があります。有用である可能性IEnumerable<int>を実装する例:

ここ
public int Length => bytes.Length/4; 
public IEnumerator<int> GetEnumerator() 
{ 
    for(int i=0; i<Length; i++) yield return this[i]; 
} 
+0

あなたのコードは私のものよりも読みやすく、読みやすいですが、まだ私はコピーなしでキャストする方法があると思います。コンパイラに知ってもらう必要があります。私はこのアプリケーションのパフォーマンスを本当に気にしています。 – pio

+0

@pioだから私はあなたがコメントで言及された '危険な'方法の1つを必要とすると思うが、私はそれに経験がない。 –

+0

@pioしかし、私のコードは配列への参照のみをコピーしないことに注意してください。もちろん、あなたがアクセスした値を「コピー」します。 –

1

(プロジェクトのプロパティをビルドするにチェックを必要とAllow unsafe code)危険なバージョンのいずれかである:配列のアドレスを取得するために必要とされる

byte[] buffer = { 255,255,255,255, 255,255,255,127 }; // little endian { -1, int.MaxValue } 

unsafe 
{ 
    fixed (byte* bytePtr = buffer) // or = &buffer[0] 
    { 
     for (int* intPtr = (int*)bytePtr; intPtr < bytePtr + buffer.Length; intPtr++) 
     { 
      *intPtr += 10; //intPtr is the address, and *intPtr is the value at that address 
     } 
    } 
} 

Debug.Print(string.Join(", ", buffer)); //"9, 0, 0, 0, 9, 0, 0, 128" { 9, int.MinValue + 9 } 

fixedガベージコレクタがアレイを異なるメモリ位置に再配置することを防止するために使用される。 bytePtr + buffer.Lengthは、bufferアレイの最後の要素の後のメモリアドレスです。 intPtrアドレスに1を加えると、4バイトだけ移動します。

安全でないバージョンは安全なBitConverterバージョンよりも2倍も速くないと思うので、そのリスクはそれほど価値はないと思います。 my previous answerの提案からはるかに優れたパフォーマンスを得ることができると思います。

+0

あなたの助けにThx! しかし、私は配列を渡して処理する必要があります。例えば、関数に渡す必要があります。もしintを渡すだけなら、int []として扱うことはできません。 私はC#をあきらめ始めていますが、Ints配列はすでにint32として正しい位置にあります。必要なのは、バイト配列ではなくInt配列として扱うようにコンパイラに指示することだけです。 – pio

関連する問題