2012-01-07 12 views
3

は説明するために:私は、入力としてintの配列を持っています。私はバイトの配列に変換する必要があります。ここで1 int = 4バイト(ビッグエンディアン)です。 C++では、私は簡単にそれをキャストすることができますし、それはバイト配列であるかのようにコピーやデータカウントせずに、フィールドへのアクセスを、その後 - ちょうど直接アクセスします。これはC#で可能ですか?そしてC#2.0では?変換INT []バイトに:それは[]、バイトだったとしてどのようにint型[]を見て?

+1

アプリケーションがネイティブでビッグエンディアンであるプラットフォーム上で実行されているそうですが?そうでなければ、変換を行うために少なくともバイトをコピーする必要があります。 –

答えて

5

はい、危険なコードを使用して:タイプセーフマネージコードで

byte* ptr2 = (byte*)(void*)ptr; 
+0

ちょうどそれをテストし、コンパイラは文句を言わない。 (少なくともC#4を使用して) – CodesInChaos

+0

@CodeInChaos歓声;私はiPadにいる - どちらかというとcscとgmcsの両方に欠けている... –

2

BitConverterクラスを見てください。あなたはintの配列を反復処理し、それぞれについてbyte[4]を取得するためにBitConverter.GetBytes(Int32)を呼び出すことができます。あなたは危険なコードを記述する場合

+0

これはデータをコピーしますが、 –

+0

コピーすることなくデータにアクセスする方法はありません。実際、この文脈では、「アクセス」と「コピー」は本質的に同義です。変数にアクセスするための最小限の可能性のある評価値である 'i'だけでも、その値がコピーされます。 –

+0

だから?多くの場合、人々は安全でないコードを使用することを望んでいます。 –

1

は、あなたは、メモリ内の配列を修正し、その先頭にポインタを取得し、そのポインタをキャストすることができます。

unsafe 
{ 
    fixed(int* pi=arr) 
    { 
    byte* pb=(byte*)pi; 
    ... 
    } 
} 

.NETのアレイは、要素の数が付いているので、あなたは安全に同一のデータを指すことint[]byte[]との間で変換することができません。 uint[]int[]の間でキャストすることができます(少なくともC#のこの機能のサポートは少し矛盾しています)。

キャストリファレンスを再解析するための組合ベースのトリックもありますが、ではなく、を使用することを強くお勧めします。


ネイティブエンディアンの順序でバイト配列から個々の整数を取得するための通常の方法はBitConverterですが、その比較的遅いです。マニュアルコードはしばしば高速です。もちろん逆変換はサポートしていません。手動で(私の2.6GHzのi3の上で毎秒読み込み、約400万人の管理)リトルエンディアンを想定して変換する

一つの方法:

byte GetByte(int[] arr, int index) 
{ 
    uint elem=(uint)arr[index>>2]; 
    return (byte)(elem>>((index&3)* 8)); 
} 

私は手動であなたが望む場合は、個々のバイトにアクセスするためにbitshifting使用するコードを書くことをお勧めします管理されたコードと一緒に行くこと、最後のパフォーマンスを望むならポインタが必要です。

エンディアンの問題にも注意する必要があります。これらのメソッドの中には、ネイティブエンディアンのみをサポートするものもあります。

+0

ビットシフトは非常によく示されています。特に、一部のプラットフォームでは安全でないことさえできません。 –

4

int [] lenghtの4倍のサイズのbyte []を作成できます。 はその後、あなたからバイト配列を取得&あなたの整数配列の谷反復:

BitConverter.GetBytes(int32); 

次はあなたが正しいオフセットに、この関数から4つのバイトをコピーBuffer.BlockCopyを使用して(私は4 *)。

BitConverter Buffer.BlockCopy

1

最も簡単な方法です:コンパイラは文句場​​合

int[] arr =... 
fixed(int* ptr = arr) { 
    byte* ptr2 = (byte*)ptr; 
    // now access ptr2[n] 
} 

を、(void*)を追加使用する:

byte[] result = new byte[intArray.Length * sizeof(int)]; 
Buffer.BlockCopy(intArray, 0, result, 0, result.Length); 

リトルエンディアンアーキテクチャー(x86やARMなど)では結果配列がリトルエンディアンになるので、あなたの質問に尋ねられたことはそれほどありませんが、 C++も同様です。

あなたがunsafe{}を使用できる場合は、他のオプションがあります。

unsafe{ 
    fixed(byte* result = (byte*)(void*)intArray){ 
    // Do stuff with result. 
    } 
} 
+2

'BlockCopy'はネイティブエンディアンを使い、リトルエンディアンではないと思う。もちろん、CLRはリトルエンディアンアーキテクチャで動作するため、実際にはほとんど違いはありません。 – CodesInChaos

+0

@CodeInChaos、そうだよ。私の言葉遣いは少しばかりだった。私は実際に彼の可能性の高いプラットフォームの選択の結果であるリトルエンディアンと、ビッグエンディアンの結果に対するOPの要件とを対比することを意味しました。私は物事を少し明確にするために言葉を修正しました。 – sblom

関連する問題