memcpy(), what should the value of the size parameter be?

85,055

Solution 1

As long as dst is declared as an array with a size, sizeof will return the size of that array in bytes:

int dst[ARRAY_LENGTH];

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

If dst just happens to be a pointer to the first element of such an array (which is the same type as the array itself), it wont work:

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

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

Solution 2

If you have allocated using malloc you must state the size of the array

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

If you have allocated with a static array you can just use sizeof

int dst2[ARRAY_LENGTH];
memcpy(dst2,src,sizeof(dst2));

Solution 3

If and when you have an array (real one) you can use the sizeof(array) trick, but note that if you refactor the code and push it somewhere where the array has decayed into a pointer (or if the memory was initially allocated in a pointer (malloc/new) you will need to pass a known size.

Ignoring the relative sizes of source and destination, that is, assuming that they are the same for the rest of the discussion, if you are using C++ I would recommend a metaprogramming trick that will give you a typesafe size count for arrays and will fail to compile if you try to use it with pointers:

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

That way:

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
}

If at any time you refactor and the code moves to a place where the array has decayed (or you replace an static array for a dynamically allocated one) the compiler will tell you that you need to correct the size calculation.

Solution 4

sizeof(dst) is correct only if dst is an array which size is known at compile time: like int arr[ARRAY_LENGTH] or a C99 variable length array; otherwise it returns the size of a pointer, not the length of the destination array.

To avoid future bug, be consistent and prefer the first form: size of type * length.

Solution 5

Will the second option always work? Regardless of the content?

The 2nd option works only if you added back the missing ) and dst is a static array (i.e. of type int[123]).

If dst has unknown size (i.e. int[]), then sizeof dst only returns the pointer size, since dst has been decayed to a pointer. In this case, you need to use sizeof(*dst)*ARRAY_LENGTH.

Share:
85,055
Tomas
Author by

Tomas

Updated on June 14, 2021

Comments

  • Tomas
    Tomas about 3 years

    I want to copy an int array to another int array. They use the same define for length so they'll always be of the same length.

    What are the pros/cons of the following two alternatives of the size parameter to memcpy()?

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

    or

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

    Will the second option always work? Regardless of the content?

    One thing that favors the last one is that if the array were to change, it'll be some house-keeping to update the memcpy()'s.