web-dev-qa-db-ja.com

startIndexを使用したmemcpy?

特定の開始点から特定の長さのコンテンツをあるバッファーから別のバッファーにコピーしたい。 memcpy()をチェックしましたが、開始インデックスも指定したいのですが、コピーされるのはコンテンツの長さだけです。

これを実行できる関数はありますか、または既存のmemcpy関数を使用して実行するための適切なアプローチはありますか?

34
soloasylum

私はいつも構文を好む

memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) );
68
Goz

必要なオフセットをバッファのアドレスに追加するだけです。

char abuff[100], bbuff[100];
....
memcpy( bbuff, abuff + 5, 10 );

これにより、abuff [5]から始まる10バイトがbbuffにコピーされます。

23
anon

オフセットをアドレスに追加するだけです。たとえば、N番目のバイトから始まるバッファーをコピーする場合:

memcpy( destination, source + N, sourceLen - N );

これにより、destinationにコピーされます。宛先もオフセットする場合は、両方にオフセットを追加します。

memcpy( destination + N, source + N, sourceLen - N );
6
sharptooth

指定したバイト数だけソースポインタを更新できるため、インデックスは必要ありません。次のラッパーはトリックを行う必要があります

void* memcpy_index(void *s1, const void *s2, size_t index, size_t n) {
  s2 = ((char*)s2)+index;
  return memcpy(s1, s2,n);
}
3
JaredPar

このサイトには、匿名の回答に加えて匿名のフォローアップを許可する方法が必要です。

なぜ、「インデックス」は1バイト単位でなければならないというこの非常識な主張を見ているのですか?それは慣習の完全に反対です。 「インデックス」は通常、シンボリックで、物理バイトオフセットが配列(またはベクトルの配列によって物理的なレイアウトさえないかもしれないが、memcpy()は要素のサイズによって決定される物理バイトオフセットの尺度です)コース)。

したがって、配列の5番目の要素には「インデックス」5がありますが、

  • 配列がchar型の場合、その「インデックス」のバイトオフセットは5です。
  • 配列のタイプがshort(x86)の場合、その「インデックス」のバイトオフセットは10です。
  • 配列がint型(x86)の場合、その「インデックス」のバイトオフセットは20です。
  • 配列が48バイトの大きなオブジェクトのタイプである場合、その「インデックス」のバイトオフセットは240です。

特定の要素にアクセスする正しい方法はどちらかです。重要な部分は、違いを理解し、どちらかを選択して、コードを正しくすることです。


言葉の意味については、もっと読みたいです。

 void* memcpy_offset(void *s1, const void *s2, size_t offset, size_t n);

より:

 void* memcpy_index(void *s1, const void *s2, size_t index, size_t n);

完全に一般的なvoid *が誤解を招く「インデックス」を持つ可能性があるという考えを見つけました。 (ここにいる間、「dest」と「source」または「in」と「out」は「s1」と「s2」よりもはるかに曖昧ではありません。変数名。)

1
Matthew

開始インデックスへのポインタを増やすだけです。

const unsigned char * src = reinterpret_cast<const unsigned char*>(your source);
unsigned char * dest = reinterpret_cast<unsigned char *>(your dest);
memcpy(dest, src + offset, len);

メモリアクセスエラーを回避するためにSTLコレクションを使用するのはどうですか?

1
Edouard A.

バッファのアドレスにインデックスを追加し、ソースパラメータとしてmemcpy()に渡します。バッファbの3番目の項目からコピー

char a[10], b[20];
::memcpy(a,b+2,10);

また、バッファー内のアイテムのタイプを考慮し、memcpy()の長さ(3番目)パラメーターはバイト単位であるため、4つのintをコピーするには、4 * sizeof(int)を配置します。おそらく16(32ビットで)ただし、ポインタ演算のため、タイプは開始アドレスには関係ありません。

int a[10], b[10];
::memcpy( a+2, b, 2*sizeof(int) );
// a+2 will be address of 3rd item in buffer a
// not address of 1st item + 2 bytes
0
CsTamas

C++を使用している場合は、memcpy()の代わりにstd :: copy()を使用することをお勧めします。 std :: copyは、イテレーターと同じくらい簡単にポインターを取ることができます。

例えば.

int src[20];
int dst[15];

// Copy last 10 elements of src[] to first 10 elements of dst[]
std::copy( src+10, src+20, dst );

Memcpy()と同様に、ポインターが有効であることを確認するのはユーザーの責任です。

注意。使用方法がパフォーマンスに重要な場合は、他の回答で詳細に説明されているmemcpy()をすばやく見つけることができますが、おそらくそれほど多くはありません。

0
Andy J Buchanan

以下のような機能があります。

template<typename T>
T* memcopy_index(T* dst,T* src,unsigned int index, unsigned int element_count)
{
    return (T*)memcpy(dst,src + index, element_count * sizeof(T));
}

以下のように使用できます。

int src[]={0,1,2,3,4,5,6};
int dst[15];

memcopy_index(dst,src,2,5);    //copy 5 elements from index 2

宛先バッファーに、エレメントをコピーするのに十分なスペースがあることを確認する必要があります。

0
Indy9000