문제

차이점은 무엇 입니까? memmove 그리고 memcpy?주로 어떤 것을 어떻게 사용하시나요?

도움이 되었습니까?

해결책

와 함께 memcpy, 대상은 소스를 전혀 겹칠 수 없습니다. 와 함께 memmove 할 수 있습니다. 이것은 그것을 의미합니다 memmove 보다 약간 느릴 수 있습니다 memcpy, 그것은 같은 가정을 할 수 없기 때문에.

예를 들어, memcpy 항상 주소를 낮은 곳에서 최고로 복사 할 수 있습니다. 소스 이후 대상이 겹치는 경우, 이는 일부 주소가 복사되기 전에 덮어 쓰는 것을 의미합니다. memmove 이 경우 이것을 감지하고 다른 방향으로 복사합니다. 그러나 이것을 확인하고 다른 (아마도 덜 효율적인) 알고리즘으로 전환하는 데 시간이 걸립니다.

다른 팁

memmove 중복되는 메모리를 처리할 수 있으며, memcpy 캔트.

고려하다

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

분명히 소스와 목적지가 겹치며 "바"로 "-bar"를 덮어 쓰고 있습니다.다음을 사용하여 정의되지 않은 동작입니다. memcpy 소스와 대상이 겹치는 경우이 경우 필요한 경우 memmove.

memmove(&str[3],&str[4],4); //fine

로부터 memcpy 남자 페이지.

memcpy () 함수는 메모리 영역에서 메모리 영역으로 N 바이트를 복사합니다. 메모리 영역이 겹치지 않아야합니다. 사용 멤버(3) 메모리 영역이 겹치는 경우.

사이의 주요 차이점 memmove() 그리고 memcpy() 그게 in입니다 memmove()완충기 - 임시 메모리 - 사용되므로 겹칠 위험이 없습니다. 반면에, memcpy() 다음이 지적한 위치에서 데이터를 직접 복사합니다. 원천 다음으로 가리키는 위치로 목적지. (http://www.cplusplus.com/reference/cstring/memcpy/)

다음 예를 고려하십시오.

  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;
    }
    

    예상대로 인쇄됩니다.

    stackoverflow
    stackstacklow
    stackstacklow
    
  2. 그러나이 예에서는 결과가 동일하지 않습니다.

    #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;
    }
    

    산출:

    stackoverflow
    stackstackovw
    stackstackstw
    

"memcpy ()"는 다음을 수행하기 때문입니다.

1.  stackoverflow
2.  stacksverflow
3.  stacksterflow
4.  stackstarflow
5.  stackstacflow
6.  stackstacklow
7.  stackstacksow
8.  stackstackstw

한 손 처리 겹치는 목적지는 그렇지 않습니다.

ISO/IEC : 9899 표준에서 간단히 설명되어 있습니다.

7.21.2.1 memcpy 함수

[...]

2 Memcpy 함수는 S2에 의해 지적 된 객체에서 N 문자를 S1에 의해 가리키는 물체로 복사합니다. 겹치는 객체 사이에서 복사가 발생하면 동작이 정의되지 않습니다.

그리고

7.21.2.2 Memmove 기능

[...]

2 Memmove 함수는 S2에 의해 지적 된 객체에서 N 문자를 S1에 의해 가리키는 물체로 복사합니다. 복사가 발생합니다 마치 S2가 가리키는 객체의 N 문자가 먼저 겹치지 않는 N 문자의 임시 배열로 복사되는 것처럼 객체는 S1과 S2를 가리키고 임시 배열의 N 문자는 S1에 의해 가리키는 물체에 복사됩니다.

내가 일반적으로 질문에 achord를 사용하는 것은 내가 필요한 기능에 따라 다릅니다.

일반 텍스트로 memcpy() 허용하지 않습니다 s1 그리고 s2 겹치는 동안 memmove() 하다.

두 가지를 모두 구현해야한다고 가정하면 구현은 다음과 같을 수 있습니다.

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
    }
}

그리고 이것은 차이를 잘 설명해야합니다. memmove 항상 그런 식으로 복사하면 여전히 안전합니다. src 그리고 dst 겹치십시오 memcpy 문서가 사용될 때 말한 것처럼 신경 쓰지 않습니다 memcpy, 두 메모리 영역 안됩니다 오버랩.

예를 들어 memcpy "Front -to Back"사본과 메모리 블록이 다음과 같이 정렬됩니다.

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

첫 바이트를 복사합니다 src 에게 dst 이미 마지막 바이트의 내용을 파괴합니다 src 이것들이 복사되기 전에. "앞면"을 복사하면 올바른 결과로 이어집니다.

이제 스왑 src 그리고 dst:

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

이 경우 "앞면으로"복사하면 "앞면"을 복사하는 것은 안전합니다. src 첫 바이트를 복사 할 때 이미 전면 근처.

당신은 그것을 알아 차렸을 것입니다 memmove 위의 구현은 실제로 겹치는 경우 테스트하지 않고 상대 위치를 확인하지만 그 자체만으로는 사본을 안전하게 만듭니다. 처럼 memcpy 일반적으로 가능한 가장 빠른 방법을 사용하여 모든 시스템에서 메모리를 복사합니다. memmove 일반적으로 다음과 같이 구현됩니다.

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);
    }
}

때때로, if memcpy 항상 "Front -Back"또는 "Back to Front"를 복사합니다. memmove 또한 사용할 수도 있습니다 memcpy 겹치는 경우 중 하나에서 memcpy 데이터가 정렬되는 방법 및/또는 복사 할 데이터의 양에 따라 다른 방식으로 복사 할 수도 있으므로 방법을 테스트하더라도 memcpy 시스템의 사본은 항상 올바른 테스트 결과에 의존 할 수 없습니다.

전화 할 사람을 결정할 때 어떤 의미가 있습니까?

  1. 당신이 확실히 알지 않는 한 src 그리고 dst 겹치지 말고 전화하십시오 memmove 그것은 항상 올바른 결과로 이어지고 일반적으로 필요한 사본 케이스에 가능한 한 빠릅니다.

  2. 확실히 알고 있다면 src 그리고 dst 겹치지 말고 전화하십시오 memcpy 결과를 요청하는 것은 중요하지 않으므로이 경우 둘 다 올바르게 작동하지만 memmove 결코 더 빠르지 않을 것입니다 memcpy 그리고 당신이 운이 좋지 않다면, 그것은 심지어 속도가 느려질 수도 있으므로 전화 만 이길 수 있습니다. memcpy.

구현하는 두 가지 명백한 방법이 있습니다 mempcpy(void *dest, const void *src, size_t n) (반환 값 무시) :

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

첫 번째 구현에서 사본은 낮은 주소에서 높은 주소로, 그리고 두 번째로 높은 수에서 낮게 진행됩니다. 복사 할 범위가 겹치는 경우 (예 : 프레임 버퍼를 스크롤 할 때와 같이), 한 번만 작동 방향 만 올바르고 다른 방향은 이후에 읽을 위치를 덮어 씁니다.

memmove() 가장 간단한 구현이 테스트됩니다 dest<src (일부 플랫폼 의존적 방식으로), 적절한 방향을 실행합니다. memcpy().

캐스팅 후에도 사용자 코드는 물론 그렇게 할 수 없습니다. src 그리고 dst 일부 콘크리트 포인터 유형으로, 그들은 일반적으로 동일한 물체를 가리키지 않으므로 비교할 수 없습니다. 그러나 표준 라이브러리는 정의되지 않은 행동을 일으키지 않고 이러한 비교를 수행하기에 충분한 플랫폼 지식을 가질 수 있습니다.


실생활에서 구현은 훨씬 더 복잡한 경향이 있으며, 더 큰 전송 (정렬 허가) 및/또는 우수한 데이터 캐시 활용으로부터 최대 성능을 얻는 경향이 있습니다. 위의 코드는 가능한 한 간단하게 지적하는 것입니다.

memmove는 겹치는 소스 및 대상 영역을 처리할 수 있지만 memcpy는 처리할 수 없습니다.둘 중에서 memcpy가 훨씬 더 효율적입니다.따라서 가능하다면 memcpy를 사용하는 것이 좋습니다.

참조: https://www.youtube.com/watch?v=Yr1YnOVG-4g 박사.Jerry Cain, (스탠포드 소개 시스템 강의 - 7) 시간:36:00

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top