memcpy() 与 memmove()

发布于 2024-10-07 03:07:04 字数 1184 浏览 10 评论 0原文

我试图理解 memcpy()< 之间的区别/a> 和 memmove(),我读过的文字是 memcpy() 不处理重叠的源和目标,而 memmove() 则负责。

但是,当我在重叠的内存块上执行这两个函数时,它们都会给出相同的结果。例如,以 memmove() 帮助页面上的以下 MSDN 示例为例: -

有没有更好的示例来理解 memcpy 的缺点以及 memmove 的工作原理代码> 解决了吗?

// crt_memcpy.c
// Illustrate overlapping copy: memmove always handles it correctly; memcpy may handle
// it correctly.

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[7] = "aabbcc";

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string

    printf( "The string: %s\n", str1 );
    memmove( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );
}

输出:

memcpy():
The string: aabbcc
New string: aaaabb

memmove():
The string: aabbcc
New string: aaaabb

I am trying to understand the difference between memcpy() and memmove(), and I have read the text that memcpy() doesn't take care of the overlapping source and destination whereas memmove() does.

However, when I execute these two functions on overlapping memory blocks, they both give the same result. For instance, take the following MSDN example on the memmove() help page:-

Is there a better example to understand the drawbacks of memcpy and how memmove solves it?

// crt_memcpy.c
// Illustrate overlapping copy: memmove always handles it correctly; memcpy may handle
// it correctly.

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[7] = "aabbcc";

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string

    printf( "The string: %s\n", str1 );
    memmove( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );
}

Output:

memcpy():
The string: aabbcc
New string: aaaabb

memmove():
The string: aabbcc
New string: aaaabb

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

吃颗糖壮壮胆 2024-10-14 03:07:04

对于您的示例没有表现出奇怪的行为,我并不完全感到惊讶。尝试将 str1 复制到 str1+2 并看看会发生什么。 (实际上可能没有什么区别,取决于编译器/库。)

通常,memcpy 以简单(但快速)的方式实现。简单地说,它只是循环数据(按顺序),从一个位置复制到另一个位置。这可能会导致源在读取时被覆盖。

memmove 做了更多工作来确保它正确处理重叠。

编辑:(

不幸的是,我找不到合适的例子,但这些就可以了)。比较 memcpymemmove 实现此处显示。 memcpy 只是循环,而 memmove 执行测试以确定循环方向以避免损坏数据。这些实现相当简单。大多数高性能实现都更加复杂(涉及一次复制字大小的块而不是字节)。

I'm not entirely surprised that your example exhibits no strange behaviour. Try copying str1 to str1+2 instead and see what happens then. (May not actually make a difference, depends on compiler/libraries.)

In general, memcpy is implemented in a simple (but fast) manner. Simplistically, it just loops over the data (in order), copying from one location to the other. This can result in the source being overwritten while it's being read.

memmove does more work to ensure it handles the overlap correctly.

EDIT:

(Unfortunately, I can't find decent examples, but these will do). Compare the memcpy and memmove implementations shown here. memcpy just loops, while memmove performs a test to determine which direction to loop in to avoid corrupting the data. These implementations are rather simple. Most high-performance implementations are more complicated (involving copying word-size blocks at a time rather than bytes).

哎呦我呸! 2024-10-14 03:07:04

memcpy 中的内存不能重叠,否则可能会出现未定义行为,而 memmove 中的内存可以重叠。

char a[16];
char b[16];

memcpy(a,b,16);           // Valid.
memmove(a,b,16);          // Also valid, but slower than memcpy.
memcpy(&a[0], &a[1],10);  // Not valid since it overlaps.
memmove(&a[0], &a[1],10); // Valid. 

memcpy 的某些实现可能仍然适用于重叠输入,但您不能指望这种行为。但是,memmove 必须允许重叠输入。

The memory in memcpy cannot overlap or you risk undefined behaviour, while the memory in memmove can overlap.

char a[16];
char b[16];

memcpy(a,b,16);           // Valid.
memmove(a,b,16);          // Also valid, but slower than memcpy.
memcpy(&a[0], &a[1],10);  // Not valid since it overlaps.
memmove(&a[0], &a[1],10); // Valid. 

Some implementations of memcpy might still work for overlapping inputs, but you cannot count on that behaviour. However, memmove must allow for overlapping inputs.

笑,眼淚并存 2024-10-14 03:07:04

仅仅因为 memcpy 不必处理重叠区域,并不意味着它不能正确处理它们。具有重叠区域的调用会产生未定义的行为。未定义的行为可以在一个平台上完全按照您的预期工作;这并不意味着它是正确或有效的。

Just because memcpy doesn't have to deal with overlapping regions, doesn't mean it doesn't deal with them correctly. The call with overlapping regions produces undefined behavior. Undefined behavior can work entirely as you expect on one platform; that doesn't mean it's correct or valid.

野生奥特曼 2024-10-14 03:07:04

memcpy 和 memove 都做类似的事情。

但要找出一个区别:

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[7] = "abcdef";

int main()
{

   printf( "The string: %s\n", str1 );
   memcpy( (str1+6), str1, 10 );
   printf( "New string: %s\n", str1 );

   strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string


   printf("\nstr1: %s\n", str1);
   printf( "The string: %s\n", str1 );
   memmove( (str1+6), str1, 10 );
   printf( "New string: %s\n", str1 );

}

给出:

The string: abcdef
New string: abcdefabcdefabcd
The string: abcdef
New string: abcdefabcdef

Both memcpy and memove do similar things.

But to sight out one difference:

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[7] = "abcdef";

int main()
{

   printf( "The string: %s\n", str1 );
   memcpy( (str1+6), str1, 10 );
   printf( "New string: %s\n", str1 );

   strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string


   printf("\nstr1: %s\n", str1);
   printf( "The string: %s\n", str1 );
   memmove( (str1+6), str1, 10 );
   printf( "New string: %s\n", str1 );

}

gives:

The string: abcdef
New string: abcdefabcdefabcd
The string: abcdef
New string: abcdefabcdef
安人多梦 2024-10-14 03:07:04

您的演示没有因为“坏”编译器而暴露 memcpy 缺点,它在调试版本中对您有帮助。然而,发布版本为您提供相同的输出,但由于优化。

    memcpy(str1 + 2, str1, 4);
00241013  mov         eax,dword ptr [str1 (243018h)]  // load 4 bytes from source string
    printf("New string: %s\n", str1);
00241018  push        offset str1 (243018h) 
0024101D  push        offset string "New string: %s\n" (242104h) 
00241022  mov         dword ptr [str1+2 (24301Ah)],eax  // put 4 bytes to destination
00241027  call        esi  

这里的寄存器%eax充当临时存储,它“优雅地”修复了重叠问题。

当复制 6 个字节(至少是其中的一部分)时,就会出现缺点。

char str1[9] = "aabbccdd";

int main( void )
{
    printf("The string: %s\n", str1);
    memcpy(str1 + 2, str1, 6);
    printf("New string: %s\n", str1);

    strcpy_s(str1, sizeof(str1), "aabbccdd");   // reset string

    printf("The string: %s\n", str1);
    memmove(str1 + 2, str1, 6);
    printf("New string: %s\n", str1);
}

输出:

The string: aabbccdd
New string: aaaabbbb
The string: aabbccdd
New string: aaaabbcc

看起来很奇怪,这也是由优化引起的。

    memcpy(str1 + 2, str1, 6);
00341013  mov         eax,dword ptr [str1 (343018h)] 
00341018  mov         dword ptr [str1+2 (34301Ah)],eax // put 4 bytes to destination, earlier than the above example
0034101D  mov         cx,word ptr [str1+4 (34301Ch)]  // HA, new register! Holding a word, which is exactly the left 2 bytes (after 4 bytes loaded to %eax)
    printf("New string: %s\n", str1);
00341024  push        offset str1 (343018h) 
00341029  push        offset string "New string: %s\n" (342104h) 
0034102E  mov         word ptr [str1+6 (34301Eh)],cx  // Again, pulling the stored word back from the new register
00341035  call        esi  

这就是为什么我在尝试复制 2 个重叠的内存块时总是选择 memmove 的原因。

Your demo didn't expose memcpy drawbacks because of "bad" compiler, it does you a favor in Debug version. A release version, however, gives you the same output, but because of optimization.

    memcpy(str1 + 2, str1, 4);
00241013  mov         eax,dword ptr [str1 (243018h)]  // load 4 bytes from source string
    printf("New string: %s\n", str1);
00241018  push        offset str1 (243018h) 
0024101D  push        offset string "New string: %s\n" (242104h) 
00241022  mov         dword ptr [str1+2 (24301Ah)],eax  // put 4 bytes to destination
00241027  call        esi  

The register %eax here plays as a temporary storage, which "elegantly" fixes overlap issue.

The drawback emerges when copying 6 bytes, well, at least part of it.

char str1[9] = "aabbccdd";

int main( void )
{
    printf("The string: %s\n", str1);
    memcpy(str1 + 2, str1, 6);
    printf("New string: %s\n", str1);

    strcpy_s(str1, sizeof(str1), "aabbccdd");   // reset string

    printf("The string: %s\n", str1);
    memmove(str1 + 2, str1, 6);
    printf("New string: %s\n", str1);
}

Output:

The string: aabbccdd
New string: aaaabbbb
The string: aabbccdd
New string: aaaabbcc

Looks weird, it's caused by optimization, too.

    memcpy(str1 + 2, str1, 6);
00341013  mov         eax,dword ptr [str1 (343018h)] 
00341018  mov         dword ptr [str1+2 (34301Ah)],eax // put 4 bytes to destination, earlier than the above example
0034101D  mov         cx,word ptr [str1+4 (34301Ch)]  // HA, new register! Holding a word, which is exactly the left 2 bytes (after 4 bytes loaded to %eax)
    printf("New string: %s\n", str1);
00341024  push        offset str1 (343018h) 
00341029  push        offset string "New string: %s\n" (342104h) 
0034102E  mov         word ptr [str1+6 (34301Eh)],cx  // Again, pulling the stored word back from the new register
00341035  call        esi  

This is why I always choose memmove when trying to copy 2 overlapped memory blocks.

时间你老了 2024-10-14 03:07:04

C11 标准草案

C11 N1570标准草案说:

7.24.2.1“memcpy函数”:

2 memcpy 函数将 s2 指向的对象中的 n 个字符复制到
s1 指向的对象。如果复制发生在重叠的对象之间,则行为
未定义。

7.24.2.2“memmove 函数”:

2
memmove函数将s2指向的对象中的n个字符复制到
s1 指向的对象。复制就像从对象中复制 n 个字符一样
s2 指向的内容首先被复制到一个包含 n 个字符的临时数组中,该数组不会
重叠s1和s2指向的对象,然后是n个字符
临时数组被复制到 s1 指向的对象中

因此,memcpy 上的任何重叠都会导致未定义的行为,并且任何事情都可能发生:坏的、什么都没有甚至是好的。不过,好的东西很少见:-)

memmove 然而,它清楚地表明一切都会发生,就好像使用了中间缓冲区一样,因此显然重叠是可以的。

然而,C++ std::copy 更宽容,并且允许重叠:std::copy 是否处理重叠范围?

C11 standard draft

The C11 N1570 standard draft says:

7.24.2.1 "The memcpy function":

2 The memcpy function copies n characters from the object pointed to by s2 into the
object pointed to by s1. If copying takes place between objects that overlap, the behavior
is undefined.

7.24.2.2 "The memmove function":

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

Therefore, any overlap on memcpy leads to undefined behavior, and anything can happen: bad, nothing or even good. Good is rare though :-)

memmove however clearly says that everything happens as if an intermediate buffer is used, so clearly overlaps are OK.

C++ std::copy is more forgiving however, and allows overlaps: Does std::copy handle overlapping ranges?

人间☆小暴躁 2024-10-14 03:07:04

memcpymemmove 的区别在于

  1. memmove 中,将指定大小的源内存复制到 buffer 中,然后移动到目标。因此,如果内存重叠,不会产生任何副作用。

  2. 对于memcpy(),源内存不占用额外的缓冲区。复制是直接在内存上完成的,因此当存在内存重叠时,我们会得到意想不到的结果。

这些可以通过以下代码观察:

//include string.h, stdio.h, stdlib.h
int main(){
  char a[]="hare rama hare rama";

  char b[]="hare rama hare rama";

  memmove(a+5,a,20);
  puts(a);

  memcpy(b+5,b,20);
  puts(b);
}

输出为:

hare hare rama hare rama
hare hare hare hare hare hare rama hare rama

The difference between memcpy and memmove is that

  1. in memmove, the source memory of specified size is copied into buffer and then moved to destination. So if the memory is overlapping, there are no side effects.

  2. in case of memcpy(), there is no extra buffer taken for source memory. The copying is done directly on the memory so that when there is memory overlap, we get unexpected results.

These can be observed by the following code:

//include string.h, stdio.h, stdlib.h
int main(){
  char a[]="hare rama hare rama";

  char b[]="hare rama hare rama";

  memmove(a+5,a,20);
  puts(a);

  memcpy(b+5,b,20);
  puts(b);
}

Output is:

hare hare rama hare rama
hare hare hare hare hare hare rama hare rama
爱*していゐ 2024-10-14 03:07:04

正如其他答案中已经指出的那样,memmove 比 memcpy 更复杂,因此它可以解决内存重叠问题。 memmove 的结果定义为将src 复制到缓冲区中,然后将缓冲区复制到dst 中。这并不意味着实际实现使用任何缓冲区,但可能会执行一些指针算术。

As already pointed out in other answers, memmove is more sophisticated than memcpy such that it accounts for memory overlaps. The result of memmove is defined as if the src was copied into a buffer and then buffer copied into dst. This does NOT mean that the actual implementation uses any buffer, but probably does some pointer arithmetic.

浮世清欢 2024-10-14 03:07:04

编译器可以优化memcpy,例如:

int x;
memcpy(&x, some_pointer, sizeof(int));

这个memcpy可以优化为:x = *(int*)some_pointer;

compiler could optimize memcpy, for example:

int x;
memcpy(&x, some_pointer, sizeof(int));

This memcpy may be optimized as: x = *(int*)some_pointer;

长发绾君心 2024-10-14 03:07:04

memcpy 的链接 http://clc-wiki.net/wiki/memcpy 中给出的代码似乎让我有点困惑,因为当我使用下面的示例实现它时,它没有给出相同的输出。

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[11] = "abcdefghij";

void *memcpyCustom(void *dest, const void *src, size_t n)
{
    char *dp = (char *)dest;
    const char *sp = (char *)src;
    while (n--)
        *dp++ = *sp++;
    return dest;
}

void *memmoveCustom(void *dest, const void *src, size_t n)
{
    unsigned char *pd = (unsigned char *)dest;
    const unsigned char *ps = (unsigned char *)src;
    if ( ps < pd )
        for (pd += n, ps += n; n--;)
            *--pd = *--ps;
    else
        while(n--)
            *pd++ = *ps++;
    return dest;
}

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 1, str1, 9 );
    printf( "Actual memcpy output: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "abcdefghij" );   // reset string

    memcpyCustom( str1 + 1, str1, 9 );
    printf( "Implemented memcpy output: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "abcdefghij" );   // reset string

    memmoveCustom( str1 + 1, str1, 9 );
    printf( "Implemented memmove output: %s\n", str1 );
    getchar();
}

输出:

The string: abcdefghij
Actual memcpy output: aabcdefghi
Implemented memcpy output: aaaaaaaaaa
Implemented memmove output: aabcdefghi

但是您现在可以理解为什么 memmove 会处理重叠问题。

The code given in the links http://clc-wiki.net/wiki/memcpy for memcpy seems to confuse me a bit, as it does not give the same output when I implemented it using the below example.

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[11] = "abcdefghij";

void *memcpyCustom(void *dest, const void *src, size_t n)
{
    char *dp = (char *)dest;
    const char *sp = (char *)src;
    while (n--)
        *dp++ = *sp++;
    return dest;
}

void *memmoveCustom(void *dest, const void *src, size_t n)
{
    unsigned char *pd = (unsigned char *)dest;
    const unsigned char *ps = (unsigned char *)src;
    if ( ps < pd )
        for (pd += n, ps += n; n--;)
            *--pd = *--ps;
    else
        while(n--)
            *pd++ = *ps++;
    return dest;
}

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 1, str1, 9 );
    printf( "Actual memcpy output: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "abcdefghij" );   // reset string

    memcpyCustom( str1 + 1, str1, 9 );
    printf( "Implemented memcpy output: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "abcdefghij" );   // reset string

    memmoveCustom( str1 + 1, str1, 9 );
    printf( "Implemented memmove output: %s\n", str1 );
    getchar();
}

Output :

The string: abcdefghij
Actual memcpy output: aabcdefghi
Implemented memcpy output: aaaaaaaaaa
Implemented memmove output: aabcdefghi

But you can now understand why memmove will take care of overlapping issue.

疾风者 2024-10-14 03:07:04

这是我写的一个例子,请参考。只有当dst所在区域位于src区域后面时,才会出现内存复制覆盖问题。

#include "stdio.h"
#include "string.h"

#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])

#define PRINT_ARRAY(arr, size, format)      \
    do {                                    \
        for (size_t i = 0; i < size; i++) { \
            printf(format, arr[i]);         \
        }                                   \
        printf("\n");                       \
    } while (0)

int test_memcpy_memmove(void)
{
    /* T1 src and dst memory do not overlap at all */
    char s1[] = {'a', 'b', 'c', '\0'};
    char s2[] = {'1', '2', '3', '\0'};

    printf("T1--------------------------:\n");
    printf("before s1 and s2:\n");
    PRINT_ARRAY(s1, ARRAY_SIZE(s1), "%c");
    PRINT_ARRAY(s2, ARRAY_SIZE(s1), "%c");
    printf("after use memcpy s2:\n");
    memcpy(s2, s1, 3);
    PRINT_ARRAY(s2, ARRAY_SIZE(s1), "%c");

    /* T2 src and dst memory overlap, and the area where dst is located is in front of the src area */
    printf("T2--------------------------:\n");
    char a[10] = {'a', 'b', 'c', 'd', 'e', 'f', '\0', '\0', '\0', '\0'};
    char b[10] = {0};
    memcpy(b, a, sizeof(char) * 10);
    printf("before a and b:\n");
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c");
    PRINT_ARRAY(b, ARRAY_SIZE(b), "%c");

    printf("after use memcpy a:\n");
    memcpy(&a[0], &a[2], 3);
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c"); // cdedef

    printf("after use memmove b:\n");
    memmove(&b[0], &b[2], 3);
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c"); // cdedef

    /* T3 !!! The memory of src and dst overlap, and the area of dst is behind the src area. */
    printf("T3--------------------------:\n");
    char c[10] = {'a', 'b', 'c', 'd', 'e', 'f', '\0', '\0', '\0', '\0'};
    char d[10] = {0};
    memcpy(d, c, sizeof(char) * 10);
    printf("before c and d:\n");
    PRINT_ARRAY(c, ARRAY_SIZE(c), "%c");
    PRINT_ARRAY(d, ARRAY_SIZE(d), "%c");

    printf("after use memcpy c:\n");
    memcpy(&c[2], &c[0], 3);
    PRINT_ARRAY(c, ARRAY_SIZE(c),
                "%c"); // ababaf >>uses memcpy to overwrite the original characters expected to be copied

    printf("after use memmove d:\n");
    memmove(&d[2], &d[0], 3);
    PRINT_ARRAY(d, ARRAY_SIZE(d),
                "%c"); // ababcf >>uses memmove and does not overwrite the characters to be copied
    return 0;
}

This is an example I wrote, please refer to it. The memory copy overwriting problem will only occur when the area where dst is located is behind the src area.

#include "stdio.h"
#include "string.h"

#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])

#define PRINT_ARRAY(arr, size, format)      \
    do {                                    \
        for (size_t i = 0; i < size; i++) { \
            printf(format, arr[i]);         \
        }                                   \
        printf("\n");                       \
    } while (0)

int test_memcpy_memmove(void)
{
    /* T1 src and dst memory do not overlap at all */
    char s1[] = {'a', 'b', 'c', '\0'};
    char s2[] = {'1', '2', '3', '\0'};

    printf("T1--------------------------:\n");
    printf("before s1 and s2:\n");
    PRINT_ARRAY(s1, ARRAY_SIZE(s1), "%c");
    PRINT_ARRAY(s2, ARRAY_SIZE(s1), "%c");
    printf("after use memcpy s2:\n");
    memcpy(s2, s1, 3);
    PRINT_ARRAY(s2, ARRAY_SIZE(s1), "%c");

    /* T2 src and dst memory overlap, and the area where dst is located is in front of the src area */
    printf("T2--------------------------:\n");
    char a[10] = {'a', 'b', 'c', 'd', 'e', 'f', '\0', '\0', '\0', '\0'};
    char b[10] = {0};
    memcpy(b, a, sizeof(char) * 10);
    printf("before a and b:\n");
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c");
    PRINT_ARRAY(b, ARRAY_SIZE(b), "%c");

    printf("after use memcpy a:\n");
    memcpy(&a[0], &a[2], 3);
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c"); // cdedef

    printf("after use memmove b:\n");
    memmove(&b[0], &b[2], 3);
    PRINT_ARRAY(a, ARRAY_SIZE(a), "%c"); // cdedef

    /* T3 !!! The memory of src and dst overlap, and the area of dst is behind the src area. */
    printf("T3--------------------------:\n");
    char c[10] = {'a', 'b', 'c', 'd', 'e', 'f', '\0', '\0', '\0', '\0'};
    char d[10] = {0};
    memcpy(d, c, sizeof(char) * 10);
    printf("before c and d:\n");
    PRINT_ARRAY(c, ARRAY_SIZE(c), "%c");
    PRINT_ARRAY(d, ARRAY_SIZE(d), "%c");

    printf("after use memcpy c:\n");
    memcpy(&c[2], &c[0], 3);
    PRINT_ARRAY(c, ARRAY_SIZE(c),
                "%c"); // ababaf >>uses memcpy to overwrite the original characters expected to be copied

    printf("after use memmove d:\n");
    memmove(&d[2], &d[0], 3);
    PRINT_ARRAY(d, ARRAY_SIZE(d),
                "%c"); // ababcf >>uses memmove and does not overwrite the characters to be copied
    return 0;
}
如若梦似彩虹 2024-10-14 03:07:04

我尝试使用 eclipse 运行相同的程序,它显示了 memcpymemmove 之间的明显区别。 memcpy() 不关心内存位置的重叠,这会导致数据损坏,而 memmove() 会先将数据复制到临时变量,然后复制到实际内存中地点。

尝试将数据从位置 str1 复制到 str1+2 时,memcpy 的输出为“aaaaaa”。问题是如何?
memcpy() 将从左到右一次复制一个字节。如您的程序“aabbcc”所示,然后
所有复制将按如下方式进行:

  1. aabbcc -> aaabcc

  2. aaabcc -> aaaacc

  3. aaaacc -> aaaaac

  4. aaaaac -> aaaaaa

memmove() 会先将数据复制到临时变量,然后复制到实际内存位置。

  1. aabbcc(实际) -> aabbcc(temp)

  2. aabbcc(temp) -> aaabcc(act)

  3. aabbcc(temp) -> aaaacc(act)

  4. aabbcc(temp) -> aaaabc(act)

  5. aabbcc(temp) -> aaaabb(act)

输出为

memcpyaaaaaa

memmoveaaaabb

I have tried to run same program using eclipse and it shows clear difference between memcpy and memmove. memcpy() doesn't care about overlapping of memory location which results in corruption of data, while memmove() will copy data to temporary variable first and then copy into actual memory location.

While trying to copy data from location str1 to str1+2, output of memcpy is "aaaaaa". The question would be how?
memcpy() will copy one byte at a time from left to right. As shown in your program "aabbcc" then
all copying will take place as below,

  1. aabbcc -> aaabcc

  2. aaabcc -> aaaacc

  3. aaaacc -> aaaaac

  4. aaaaac -> aaaaaa

memmove() will copy data to temporary variable first and then copy to actual memory location.

  1. aabbcc(actual) -> aabbcc(temp)

  2. aabbcc(temp) -> aaabcc(act)

  3. aabbcc(temp) -> aaaacc(act)

  4. aabbcc(temp) -> aaaabc(act)

  5. aabbcc(temp) -> aaaabb(act)

Output is

memcpy : aaaaaa

memmove : aaaabb

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文