Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 768
Tomas Avatar asked Apr 21 '10 07:04

Tomas


People also ask

When should memcpy be used?

The function memcpy() is used to copy a memory block from one location to another. One is source and another is destination pointed by the pointer. This is declared in “string.

Does memcpy copies byte by byte?

memcpy() — Copy Bytes Threadsafe: Yes. The memcpy() function copies count bytes of src to dest . The behavior is undefined if copying takes place between objects that overlap. The memmove() function allows copying between objects that might overlap.

Does memcpy work with arrays?

Memcpy copies data bytes by byte from the source array to the destination array. This copying of data is threadsafe.


4 Answers

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*) 
like image 72
Timbo Avatar answered Oct 26 '22 14:10

Timbo


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.

like image 29
Gregory Pakosz Avatar answered Oct 26 '22 14:10

Gregory Pakosz


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.

like image 42
David Rodríguez - dribeas Avatar answered Oct 26 '22 15:10

David Rodríguez - dribeas


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));
like image 45
Scott Wales Avatar answered Oct 26 '22 14:10

Scott Wales