24

int配列を別の配列にコピーしたいint。それらは長さに対して同じ定義を使用するため、常に同じ長さになります。

size パラメーターの次の 2 つの代替案の長所と短所は何memcpy()ですか?

memcpy(dst, src, ARRAY_LENGTH*sizeof(int));

また

memcpy(dst, src, sizeof(dst));

2 番目のオプションは常に機能しますか? 内容に関係なく?

最後のものを支持することの 1 つは、配列が変更された場合、memcpy().

4

12 に答える 12

41

dstサイズのある配列として宣言されている限り、はsizeofその配列のサイズをバイト単位で返します。

int dst[ARRAY_LENGTH];

memcpy( dst, src, sizeof(dst) ); // Good, sizeof(dst) returns sizeof(int) * ARRAY_LENGTH

そのdstような配列の最初の要素(配列自体と同じ型)へのポインターである場合、それは機能しません:

int buffer[ARRAY_LENGTH];
int* dst = &buffer[0];

memcpy( dst, src, sizeof(dst) ); // Bad, sizeof(dst) returns sizeof(int*)
于 2010-04-21T07:39:40.810 に答える
5

sizeof(dst)dstがコンパイル時にサイズがわかっている配列である場合にのみ正しいですint arr[ARRAY_LENGTH]。またはC99可変長配列のように。それ以外の場合は、宛先配列の長さではなく、ポインターのサイズを返します。

将来のバグを回避するために、一貫性を保ち、最初の形式であるタイプのサイズ*長さを優先してください。

于 2010-04-21T07:36:32.000 に答える
5

mallocを使用して割り当てた場合は、配列のサイズを指定する必要があります

int * src = malloc(ARRAY_LENGTH*sizeof(*src));
int * dst1 = malloc(ARRAY_LENGTH*sizeof(*dst1));
memcpy(dst1,src,ARRAY_LENGTH*sizeof(*dst1));

静的配列を割り当てた場合は、次を使用できますsizeof

int dst2[ARRAY_LENGTH];
memcpy(dst2,src,sizeof(dst2));
于 2010-04-21T07:39:01.870 に答える
5

配列(実際の配列)がある場合は、このsizeof(array)トリックを使用できますが、コードをリファクタリングして、配列がポインターに崩壊した場所にプッシュする場合(またはメモリが最初にポインターに割り当てられた場合(malloc)に注意してください/new) 既知のサイズを渡す必要があります。

ソースと宛先の相対的なサイズを無視します。つまり、残りの説明ではそれらが同じであると仮定します。C++ を使用している場合は、配列の型安全なサイズ カウントを提供し、失敗するメタプログラミング トリックをお勧めします。ポインターで使用しようとする場合はコンパイルします。

template <typename T, int N>
inline int array_memory_size( T (&a)[N] ) { return sizeof a; }

その方法:

int main() {
   int array[10];
   int *ptr = array;
   int orig[10] = { 0 };
   memcpy( array, orig, array_memory_size(array) ); // ok
   //memcpy( ptr, orig, array_memory_size(ptr) ); // compilation error
}

リファクタリングを行い、コードが配列が減衰した場所に移動した場合 (または静的配列を動的に割り当てられた配列に置き換えた場合)、コンパイラはサイズの計算を修正する必要があることを通知します。

于 2010-04-21T07:47:38.860 に答える
3

2番目のオプションは常に機能しますか?内容に関係なく?

) 2番目のオプションは、欠落し dstているものを追加し直して静的配列(つまりタイプ)である場合にのみ機能しますint[123]

dstが不明なサイズ(つまりint[])の場合、はポインタに減衰されているsizeof dstため、ポインタサイズのみを返します。dstこの場合、を使用する必要がありますsizeof(*dst)*ARRAY_LENGTH

于 2010-04-21T07:39:28.530 に答える
1

sizeof(X)は、常に「X」のバイト数を示します。Xが10のuint16_t配列の場合、sizeof(X)は20を返します。

uint16_t X[10]={0};
cout<<"sizeof x: "<<sizeof(X);

$> sizeof x: 20

要素の数が必要な場合は、バイト演算を少し行う必要があります
。8ビット=1バイト
16
ビット=2バイト32ビット=4バイト
64ビット=8バイト

なので、要素の数を取得するには、次のようにします。

 numb_of_elements = ( sizeof(X)/sizeof(X[0]) );

その結果:

uint32_t source[100]={0};
memcpy((void*) dest, (void*) source, ( sizeof(source)/sizeof(source[0]) ));

もちろん、(sizeof(X)/ sizeof(X [0]))を定数/変数にして、毎回計算しないようにすることをお勧めします。(コンパイラが常にこれを最適化するかどうかはわかりません)

于 2013-03-08T18:30:16.353 に答える
1

dstがint*型であるとすると、sizeof(dst)はポインター自体のサイズを返します(つまり、32ビットシステムでは4、64ビットシステムでは8)。したがって、2番目の例では、この数のバイトのみがすべてコピーされます。最初のものは、コンテンツの実際のサイズを正しく使用します。

于 2010-04-21T07:38:07.620 に答える
1

2番目のオプションは常に機能しますか?内容に関係なく?

両方の条件が満たされた場合にのみ機能します。

  • dstポインタではなく、通常の配列です
  • srcdst同じサイズです
于 2010-04-21T07:40:57.670 に答える
0

場合によります。arr とポインターはどちらも配列ですが、sizeof() は、コンパイル時に宣言された arr の正しいサイズのみを返します。

int main() {
        int arr[10];
        int * pointer;
        pointer = (int *) malloc(10 * sizeof(int));
        printf("%d\n", sizeof(arr)); // 40
        printf("%d\n", sizeof(pointer)); // 4 or 8
        free(pointer);
}
于 2010-04-21T07:41:53.150 に答える
0

dst が (たとえば malloc を使用して) ヒープから割り当てられた場合、2 番目の解決策は機能しません。sizeof(dst) は、コンパイラに認識されている場合にのみ機能します。たとえば、次の例は sizeof(dst) がポインターのサイズ (4 ~ 8 バイト) と等しくなるため失敗します。

#define ARRAY_LENGTH 10
int *dst;

dst = malloc(ARRAY_LENGTH*sizeof(int));
memcpy(dst, src, sizeof(dst)); // sizeof dst in this case would be 4 bytes on 32 bit system

このコード セグメントは毎回動作します。

#define ARRAY_LENGTH 10
int *dst;

dst = malloc(ARRAY_LENGTH*sizeof(int));
memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); // sizeof would be 40 bytes
于 2010-04-21T07:46:10.193 に答える
-1

どうですか?

memcpy(dst, src, &src[ARRAY_LENGTH] - &src[0]);

これは、個々の要素のサイズが実際の配列内の各項目のサイズよりも小さい場合でも機能するはずです。

于 2010-04-21T07:55:22.937 に答える