Difference between memcpy and memmove
Solved
leoliom
Posted messages
187
Status
Member
-
leoliom Posted messages 187 Status Member -
leoliom Posted messages 187 Status Member -
Hello, I have read a lot of documents, I have looked at plenty of examples but I cannot understand the overlapping stuff and others. I want to understand so that I can anticipate what the program will display to me.
Configuration: iPad / Chrome 98.0.4758.97
Configuration: iPad / Chrome 98.0.4758.97
9 answers
-
jeannets Posted messages 28395 Registration date Status Contributor Last intervention Ambassadeur 6 603
Hello,
Memcpy is a memory copy to another address, without destroying the original
https://man7.org/linux/man-pages/man3/memcpy.3.html
Whereas Memmove is a memory move, unlike Memcpy, it clears the source..
https://www.man7.org/linux/man-pages/man3/memmove.3.html
The attributes define the source, the destination, and the size of the values being moved or copied...
Of course, to keep everything in sync, you need to know your lesson and the values in motion. Create examples on graph paper.. -
I also read this site but I didn't understand. As you say, the only way to understand is through a diagram, but I'm struggling with that.
Maybe a small example will help me better understand. -
The two functions are only distinguishable in cases of overlap. This occurs when there are elements present in both the source to copy and the destination.
For example, if you want to copy the first 4 elements of the following table into the last 4:+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+
If you usememmove()
, you will get the following result (the last 4 receive exactly what was in the first 4)+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 1 | 2 | 3 | 4 |
+---+---+---+---+---+---+---+
If you usememcpy()
, this function is a bit "dumb"; it operates quickly but doesn't "think" much! It is likely to give you the following result:+---+---+---+---+---+---+---+
This is a guess; try to understand what caused it to fail and attempt to write code that addresses this, or try to write your own
| 1 | 2 | 3 | 1 | 2 | 3 | 1 |
+---+---+---+---+---+---+---+memcpy()
function and see why the end result is not correct.
Therefore, if there is no overlap, the functions are equivalent (butmemcpy()
is faster), whereas if there is overlap, thememcpy()
function may produce an incorrect result. -
According to your example:
int tab[10] = {1, 2, 3, 4, 5, 6, 7}; int tab2[10]; strncpy(tab2,tab1,4); memmove(tab + 3, tab2, strlen(tab)) memcpy(tab + 3, tab2, strlen(tab))
Is it correct?
I didn't understand the sentence It's when some elements are both in the source to copy and in the destination.
For example, in your example, there is overlap for which number?-
You indeed did not understand. There is only one array and we make copies within the array. If there are two arrays then
memcpy()
andmemmove()
are indistinguishable.
Andstrncpy()
andstrlen()
are functions that apply to strings. Here they are arrays of integers, it has nothing to do with it and these functions do anything in your code!
My example is:int tab[7] = {1, 2, 3, 4, 5, 6, 7}; memmove( &tab[3], &tab[0], 4*sizeof(int) ); // copy tab[0]tab[1]tab[2]tab[3] into tab[3]tab[4]tab[5]tab[6]. for ( int i = 0 ; i < 7 ; ++i ) printf( "%d ", tab[i] );
-
-
I think it's good, I've understood the subtlety between the two, it took me a long time to grasp it
Thank you -
Bonjour,
To understand the operation ofmemcpy
andmemmove
, I looked at their implementation in C, but strangely, they don't always do the same thing. Formemmove
, it works, but notmemcpy
.
Example :
#include <stdio.h> #include <string.h> void * Memcpy(void* dst, const void* src, unsigned int cnt) { char *pszDest = (char *)dst; const char *pszSource =( const char*)src; if((pszDest!= NULL) && (pszSource!= NULL)) { while(cnt) //until cnt { //Copy byte by byte *(pszDest++)= *(pszSource++); --cnt; } } return dst; } int main(void){ char chaine[7] = "aabbcc"; Memcpy(chaine + 2, chaine, 4); printf("%s\n", chaine); return 0; }-
Memcpy
returnsaaaaaa
; -
memcpy
returnsaaaabb
.
If I take another implementation from the Internet:
#include <string.h> #include <stdio.h> void myMemCpy(void *dest, void *src, size_t n){ // Typecast src and dest addresses to (char *) char *csrc = (char *)src; char *cdest = (char *)dest; // Copy contents of src[] to dest[] for (int i = 0; i < n; i++) cdest[i] = csrc[i]; } int main(void){ char str1[7] = "aabbcc"; myMemMove(str1 + 2, str1, 4); printf("New string: %s\n", str1); return 0; }-
mymencpy
returnsaaaaaa
; -
memcpy
returnsaaaabb
.
I don't understand anymore, their implementation in C seemed correct to me. What is wrong? What is missing from these functions for them to do the same job asmemcpy
? -
-
Hello,
What domemmove
andmemcpy
do?
Generally, you just need to look at what is described inman memmove
andman memcpy
(to be typed into Google or a terminal if you are on Linux)memcpy
copies a block of memory from one address to another address. The target block must be pre-allocated in memory to accommodate the source block; otherwise, you typically get a segmentation fault. The copying is done byte by byte (and as a reminder, an ASCII character (char
) takes up one byte, which is why this function is quite similar tostrcpy
and thus in<string.h>
): you read the current source byte, copy it into the corresponding target byte, and repeat the operation until the entire block has been processed.- Officially,
memmove
moves a block of memory from one address to another address. The target block must be pre-allocated in memory to accommodate the source block; otherwise, you typically get a segmentation fault. There is no guarantee on what will remain at the source block level, but most implementations simply leave it as is to improve performance (and for these implementations,memmove
does exactly the same thing asmemcpy
when the source and target blocks do not overlap). In these situations,memmove
is preferred for code readability. However, the source block should no longer be read because, depending on the implementation, it may have been reset.
What happens if the blocks overlap?
Now, let's take a closer look at what happens if the source and target blocks overlap. Here, you need to be cautious, as you might fear edge effects (typically if you're writing in the area you're about to read):- According to this page,
memmove
uses an intermediate buffer to guard against these edge effects. - According to this page, this is not the case for
memcpy
, so you need to be careful about what you're doing.
Why is there astrcpy
function andmemcpy
?
There are several reasons, and before starting, it's important to understand how a string is stored in memory. The core issue is that a string can be arbitrarily long (unlike auint32_t
, which is defined to be exactly 32 bits, or 4 bytes). How to keep track of the length?
The choice that was made is to mark the string with a terminating character'\0'
(which corresponds to theuint8_t
0
). All thestr*
functions (strcpy
,strlen
, ...) andprintf
rely on this terminating character to know when to stop. This means that the string"abc"
is 4 bytes{'a', 'b', 'c', '\0'}and not 3 as one might think. This means you must not forget this famous terminating character as soon as you manipulate strings. Without it, thestr*
functions will continue until they (by chance) encounter a byte that equals 0, often outside of an allocated memory area, leading to a segmentation fault.
Returning tomemcpy
, we see that it can reproducestrcpy
provided you know the length of the string to be copied (including its terminating'\0'
character).
Sincememcpy
is designed to manipulate an arbitrary block of memory—which is why, in its prototype, the typeconst void *
is used for the source block (read-only) and the typevoid *
is used for the target block (read-write)—(in particular, something that is not a string and thus not necessarily terminated by'\0'
), you need to indicate how many bytes to copy. This is the role of its third parameter.
Back to your code
In your case, since you are manipulating strings, it is not enough to just copy the letters for everything to go smoothly; you must ensure that the string you are going to copy or display has its terminating character'\0'
. This is something guaranteed bystrcpy
, but not bymemcpy
.
Good luck! -
Ah, so the implementations of these functions are not correct because we don't take into account the terminal character at the end of the string
Should I modify the code so that it adds this character at the end of the copy for it to work?-
>>> So the implementations of these functions are not correct because they do not take into account the terminal character at the end of the string.
No. Did you see anywhere that memcpy() was supposed to add a string terminator?
>> Do I need to modify the code so that it adds this character at the end of the copy for it to work?
No.
The function memcpy(), the function mymencpy(), and the function Memcpy() are all three compliant.
The standard states:
- if there is no overlap, the function must copy (you can check that all three functions perform the copy correctly).
- if there is overlap, the result is completely unpredictable (so the result is entirely arbitrary, it makes no sense to compare results in this case!)
It is entirely possible that the function memcpy() behaves differently if you change the context!char str1[7] = "aabbcc"; char str2[7] = "aabbcc"; memcpy(str1 + 2, str1, 4); printf("New string: %s\n", str1); memcpy(str2 + 2, str2, 4); printf("New string: %s\n", str2);This code can very well return 2 different results with apparently the same input data, or have a different result in debug version and in release version, try it. It is futile to want to reproduce what you see in the case where the function has an undefined result!- To complement what Dalfab said:
- the
str*
functions assume that the memory block to copy is of arbitrary size but can be viewed as a null-terminated string'\0'
; - the
mem*
functions do not make any assumptions about a stopping character (which allows for copying any sequence of bytes, but require a size to know when to stop); - in any case, these functions should only read and write in memory areas allocated by the program, otherwise a segmentation fault will be triggered.
- the
-
-
Thank you for all these answers, I understand better now.