私は、 memcpy
はこれを行う方法ではないと言います。しかし、最高の方法を見つけることは、データがメモリにどのように格納されるかによって大きく異なります。
まず、宛先変数のアドレスを取得する必要はありません。ローカル変数の場合は、コンパイラにプロセッサレジスタに配置するオプションを与えるのではなく、スタックに強制します。これだけでは非常に高価になる可能性があります。
最も一般的な解決策は、バイトごとにデータを読み取り、結果を算術的に結合することです。例えば:
uint16_t res = ( (((uint16_t)char_array[high]) << 8)
| char_array[low]);
あなたがより多くの選択肢を持っているので、32ビットの場合の式は少し複雑です。最適なアセンブラ出力を確認することができます。
Alt 1:パリを構築し、それらを結合する:
uint16_t low16 = ... as example above ...;
uint16_t high16 = ... as example above ...;
uint32_t res = ( (((uint32_t)high16) << 16)
| low16);
Alt 2:一度に8ビットずつシフト:
uint32_t res = char_array[i0];
res = (res << 8) | char_array[i1];
res = (res << 8) | char_array[i2];
res = (res << 8) | char_array[i3];
上記のすべての例は、インデックス値によってどの部分を読み込むかを決めるため、使用するプロセッサのエンディアンに中立です。
1)デバイスのエンディアン(バイトオーダ)が、バイトが配列に格納されている順序と一致し、2)配列が整列されたメモリアドレスに配置されていることがわかっている場合、次のような解決策が可能です。後者の場合はマシンに依存しますが、16ビット配列を表すchar配列が偶数アドレスで開始し、32ビットの場合は4で割り切れるアドレスで開始する必要があります。この場合、いくつかのポインタトリックの後に、単にアドレスを読むことができます:
uint16_t res = *(uint16_t *)&char_array[xxx];
xxx
はメモリの最初のバイトに対応する配列インデックスです。これは、最小値のインデックスと同じではない可能性があることに注意してください。
endianess-neutralなので、最初のクラスのソリューションを強くお勧めします。
とにかく、両方ともあなたの memcpy
よりも速いです。