What is the difference between memmove and memcpy?

What is the difference between memmove and memcpy ? Which one do you usually use and how?

+107
c memcpy memmove
Jul 29 '09 at 16:01
source share
13 answers

With memcpy recipient cannot completely overlap the source. With memmove he can. This means that memmove may be slightly slower than memcpy , as it cannot make the same assumptions.

For example, memcpy can always copy addresses from low to high. If the destination overlaps after the source, this means that some addresses will be rewritten before copying. memmove detect this and copy in a different direction - from high to low - in this case. However, checking this and switching to another (possibly less efficient) algorithm takes time.

+149
Jul 29 '09 at 16:03
source share

memmove can handle overlapping memory, memcpy cannot.

Consider

 char[] str = "foo-bar"; memcpy(&str[3],&str[4],4); //might blow up 

Obviously, the source and destination are now overlapping, we are rewriting "-bar" with "bar". This behavior is undefined using memcpy if the source and destination overlap, so in this case we need memmove .

 memmove(&str[3],&str[4],4); //fine 
+31
Jul 29 '09 at 16:03
source share

On memcpy page

The memcpy () function copies n bytes from the src memory region to the Dest memory region. Areas of memory should not overlap. Use memmove (3) if memory areas overlap.

+22
Jul 29 '09 at 16:02
source share

The main difference between memmove() and memcpy() is that memmove() uses a buffer - temporary memory - so there is no risk of overlapping. memcpy() , on the other hand, directly copies data from the location specified by the source to the location specified by the destination. ( http://www.cplusplus.com/reference/cstring/memcpy/ )

Consider the following examples:

  1.  #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *first, *second; first = string; second = string; puts(string); memcpy(first+5, first, 5); puts(first); memmove(second+5, second, 5); puts(second); return 0; } 

    As you expected, this will print:

     stackoverflow stackstacklow stackstacklow 
  2. But in this example, the results will not be the same:

     #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *third, *fourth; third = string; fourth = string; puts(string); memcpy(third+5, third, 7); puts(third); memmove(fourth+5, fourth, 7); puts(fourth); return 0; } 

    Exit:

     stackoverflow stackstackovw stackstackstw 

This is because memcpy () does the following:

 1. stackoverflow 2. stacksverflow 3. stacksterflow 4. stackstarflow 5. stackstacflow 6. stackstacklow 7. stackstacksow 8. stackstackstw 
+13
Aug 07 '14 at 10:11
source share

One handles intersecting destinations, and the other does not.

+10
Jul 29 '09 at 16:02
source share

just from the standard ISO / IEC: 9899, โ€‹โ€‹it's well described.

7.21.2.1 memcpy function

[...]

2 The memcpy function copies n characters from the object pointed to by s2 to the object pointed to by s1. If copying occurs between overlapping objects, the behavior is undefined.

and

7.21.2.2 memmove function

[...]

2 The memmove function copies n characters from the object pointed to by s2 to the object pointed to by s1. Copying occurs as if n characters from the object pointed to by s2 are first copied to a temporary array of n characters that do not overlap the objects pointed to by s1 and s2, and then n characters from the temporary array are copied to the object pointed to s1.

Which I usually use depending on the question depends on what kind of functionality I need.

In text format, memcpy() not allowed to overlap s1 and s2 , and memmove() is not.

+6
May 8 '15 at 10:48
source share

Assuming you have to implement both options, the implementation might look like this:

 void memmove ( void * dst, const void * src, size_t count ) { if ((uintptr_t)src < (uintptr_t)dst) { // Copy from back to front } else if ((uintptr_t)dst < (uintptr_t)src) { // Copy from front to back } } void mempy ( void * dst, const void * src, size_t count ) { if ((uintptr_t)src != (uintptr_t)dst) { // Copy in any way you want } } 

And that should explain the difference pretty well. memmove always copies in such a way that it is still safe if src and dst overlap, whereas memcpy just doesn't care, as the documentation says, when using memcpy two memory areas should not overlap.

For example, if memcpy copies "front to back" and the memory blocks are aligned like this

 [---- src ----] [---- dst ---] 

copying the first src byte to dst already destroys the contents of the last src bytes before they were copied. Only back-to-front copying will produce the correct results.

Now swap src and dst :

 [---- dst ----] [---- src ---] 

In this case, it is only safe to copy "front to back", since copying "front to back" will destroy src near its front already when copying the first byte.

You may have noticed that the memmove above, the memmove implementation does not even check if they really overlap, it just checks their relative positions, but this alone will make the copy safe. Since memcpy usually uses the fastest way to copy memory on any system, memmove usually implemented as follows:

 void memmove ( void * dst, const void * src, size_t count ) { if ((uintptr_t)src < (uintptr_t)dst && (uintptr_t)src + count > (uintptr_t)dst ) { // Copy from back to front } else if ((uintptr_t)dst < (uintptr_t)src && (uintptr_t)dst + count > (uintptr_t)src ) { // Copy from front to back } else { // They don't overlap for sure memcpy(dst, src, count); } } 

Sometimes, if memcpy always copies front to back or front to back, memmove may also use memcpy in one of the overlapping cases, but memcpy may even copy differently depending on how the data is aligned and / or how much the data should be copied, so even if you checked how memcpy copies on your system, you cannot rely on the fact that the test results will always be correct.

What does this mean for you when you decide who to call?

  1. If you donโ€™t know for sure that src and dst do not overlap, call memmove as it will always produce the correct results and, as a rule, will be as fast as possible for the copying case you need.

  2. If you know for sure that src and dst do not overlap, call memcpy no matter which one you call for the result, both will work correctly in this case, but memmove will never be faster than memcpy and if you Unfortunately, it can even be slower, so you can only win a memcpy call.

+5
Apr 14 '18 at 23:59 on
source share

I tried working on the code: The main reason I want to know the difference between memcpy and memmove .

 #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *third, *fourth; third = string; fourth = string; puts(string); memcpy(third+5, third, 7); puts(third); memmove(fourth+5, fourth, 7); puts(fourth); return 0; } 

gives lower output

 stackoverflow stackstackovw stackstackstw 

Now I replaced memmove with memcpy and I got the same result

 #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *first, *second; first = string; second = string; puts(string); memcpy(first+5, first,7); puts(first); memcpy(second+5, second, 7); puts(second); return 0; } 

Output:

 stackoverflow stackstackovw stackstackstw 
0
Mar 22 '15 at 17:06
source share

char string [] = "stackoverflow";

 char *first, *second; first = string; second = string; puts(string); 

o / p - stackoverflow

 memcpy(first+5, first,7); puts(first); 

There are 7 characters pointed to by the second ie "stackov" inserted at +5, resulting in

o / p - stackstackovw

 memcpy(second+5, second, 7); puts(second); 

here the input line is "stackstackovw", 7 characters that the second one points to (ie "stackst") is copied to the buffer, and then pasted at +5, getting

o / p - stackstackstw

0 ----- + 5
stack stackst w

0
May 20 '16 at 10:32
source share

There are two obvious ways to implement mempcpy(void *dest, const void *src, size_t n) (ignoring the return value):

  •  for (char *p=src, *q=dest; n-->0; ++p, ++q) *q=*p; 
  •  char *p=src, *q=dest; while (n-->0) q[n]=p[n]; 

In the first implementation, the copy comes from low to high addresses, and in the second - from high to low. If the copied range overlaps (for example, when scrolling through the framebuffer), then only one direction of the operation is correct, and the other will overwrite the locations that will later be read.

A memmove() implementation in its simplest case will check dest<src (specifically on the platform) and execute the corresponding direction memcpy() .

Custom code cannot do this, of course, because even after casting src and dst for a certain type of pointer, they donโ€™t (generally) point to the same object and therefore canโ€™t compare, but the standard library may have sufficient platform knowledge for perform such comparisons without invoking Undefined Behavior.




Please note that in real life, implementations are usually much more difficult to get maximum performance from large transfers (with alignment enabled) and / or good use of the data cache. The code above is as simple as possible.

0
May 30 '16 at 15:18
source share

memmove can work with overlapping source and destination regions, while memcpy cannot. Among them, memcpy is much more efficient. So, it's better to use USER if you can.

Link: https://www.youtube.com/watch?v=Yr1YnOVG-4g Dr. Jerry Cain, (Stanford Lecture Initiative System - 7) Time: 36:00

0
Dec 10 '16 at 2:46
source share

memmove, which takes care of memory overlay as opposed to memset. but what memory overlaps anyway?

Suppose we have an array of 5 characters, where each character has a byte length

 +++++++++++++++++++++++++++++++ | 'a' | 'b' | 'c' | 'd' | 'e' | +++++++++++++++++++++++++++++++ 0x100 0x101 0x102 0x103 0x104 

now according to the memcpy man page, it takes 3 arguments, a pointer to the target memory block, a pointer to the original memory block, and the size of the bytes to be copied.

What if destination is 0x102, source is 0x100 and size is 3? there is a coincidence of memory. that is, 0x100 will be copied to 0x102, 0x101 will be copied to 0x103, and 0x102 will be copied to 0x104.

note that we first copied to 0x102 and then copied from 0x102, which means that the value that was originally at 0x102 was lost, since we overwritten it with the value that we copied to 0x102 before copying from it. so that we would end up with something like

 +++++++++++++++++++++++++++++++ | 'a' | 'b' | 'a' | 'b' | 'a' | +++++++++++++++++++++++++++++++ 0x100 0x101 0x102 0x103 0x104 instead of +++++++++++++++++++++++++++++++ | 'a' | 'b' | 'a' | 'b' | 'c' | +++++++++++++++++++++++++++++++ 0x100 0x101 0x102 0x103 0x104 

how does a function like memmove take care of memory overlap? according to his man page, he first copies the bytes that should be copied to the temporary array, and then inserts them into the destination block, as opposed to a function such as memcpy, which copies directly from the source block to the destination block.

-one
Apr 21 '19 at 6:11
source share

The technical difference has been well documented by previous answers. Practical differences should also be noted:

Memcpy will require approximately twice as much memory to complete the same task, but memmove can take significantly longer than memcpy.

Example:

Say you have a list of 100 items in memory that accept 100 MB of memory. You want to reset 1st element so that you have 99.

To get a new list of 99 Memcpy items, you will need the original 100 MB and an additional 99 MB. Approximately 199 MB to complete the operation, but should be very fast.

Memmove, in the worst case scenario, you will need the original 100 MB and will move each memory item 1 item at a time. It only requires 100 MB, but will be significantly slower than Memcpy.

Of course, creating a new pointer pointing to the second element in your list will have the same effect of โ€œdroppingโ€ the first element from your list, but the example shows the differences in memcpy and memmove.

- CHANGE TO HELP COMPLETE MY CARPIAN RESPONSE -
Yes, the implementation of memcpy () and memmove () probably doesn't differ in memory usage (I really don't know), but the way you use them will greatly affect the memory usage of your program. This is what I meant by the practical differences memcpy () and memmove ().

 int SIZE = 100; Item *ptr_item = (Item *) malloc(size_of(Item) * SIZE); Item *ptr_src_item = ptr_item + 1; Item *ptr_dst_item = ptr_item; memmove(ptr_dst_item, ptr_src_item, SIZE - 1); 

Creates a list of items with no first item. This essentially does not require more memory for your program than what is required to allocate the original ptr_item memory block. You cannot do this with memcpy () ... if you did, your program would have to allocate approximately twice as much memory.

 int SIZE = 100; Item *ptr_src_item = (Item *) malloc(size_of(Item) * SIZE); Item *ptr_dst_item = (Item *) malloc(size_of(Item) * (SIZE - 1)); memcpy(ptr_dst_item, ptr_src_item, SIZE - 1); 

In this second block of code, the program will require twice as much memory as the first block. However, this second block should run much faster than the first block, especially as the size increases.

The way I tried to explain the practical differences in the two ... but maybe I'm wrong about that too?

-10
Jul 29 '09 at 17:00
source share



All Articles