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
28378
Registration date
Status
Contributor
Last intervention
Ambassadeur
6 599
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..
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.
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:
If you use
If you use
Therefore, if there is no overlap, the functions are equivalent (but
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 use
memmove(), 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 use
memcpy(), 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 (but
memcpy()is faster), whereas if there is overlap, the
memcpy()function may produce an incorrect result.
According to your example:
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?
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
And
My example is:
memcpy()and
memmove()are indistinguishable.
And
strncpy()and
strlen()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
Thank you
Bonjour,
To understand the operation of
Example :
If I take another implementation from the Internet:
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 as
To understand the operation of
memcpyand
memmove, I looked at their implementation in C, but strangely, they don't always do the same thing. For
memmove, it works, but not
memcpy.
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 as
memcpy?
Hello,
What do
Generally, you just need to look at what is described in
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):
Why is there a
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 a
The choice that was made is to mark the string with a terminating character
Returning to
Since
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
Good luck!
What do
memmoveand
memcpydo?
Generally, you just need to look at what is described in
man memmoveand
man 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 a
strcpyfunction and
memcpy?
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 a
uint32_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 the
uint8_t
0). All the
str*functions (
strcpy,
strlen, ...) and
printfrely 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, the str*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 to
memcpy, we see that it can reproduce
strcpyprovided you know the length of the string to be copied (including its terminating
'\0'character).
Since
memcpyis designed to manipulate an arbitrary block of memory—which is why, in its prototype, the type
const void *is used for the source block (read-only) and the type
void *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 by
strcpy, but not by
memcpy.
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?
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!
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.