Home » 레퍼런스 » C » c언어 memcpy memmove 함수로 메모리 복사를 해 봅시다.

c언어 memcpy memmove 함수로 메모리 복사를 해 봅시다.

c언어 memcpy 함수와 memmove 함수는 메모리에 있는 내용을 일정 byte 만큼, 메모리의 다른 공간으로 복사합니다.이 둘에 대한 것을, 이 글에서 한꺼번에 알아보겠습니다.


함수의 원형

두 함수는 모두 string.h에 속해 있습니다. memory.h에 속해 있는 것 같지만, 아닙니다. 이 점 주의하셔야 합니다.

[그림 1] 두 함수의 원형

원형을 보면, 3개의 인자를 받고 있어요. 어느 위치에서 어느 위치로 얼마만큼 복사할 것인지를 넘겨주게 됩니다.

  • dest
    • 복사받을 위치를 의미합니다.
  • src
    • 원본 소스를 의미합니다.
  • size
    • 몇 바이트를 복사할 것인지 의미합니다.

문자열 복사할 때에는 memcpy, memmove 대신에 strcpy를 써야 합니다. 이는, 복사의 종료 조건이 다르기 때문입니다. 전자는 byte였다면, 후자는 널 문자를 만나면 종료합니다. 그런데 왜 이 두 함수가 별도로 있는 것일까요?

[그림 2] c언어 memcpy 함수 설명

먼저, memcpy의 추가 설명을 봅시다. src에서 dest로 복사하는데, 복사하는 쪽과 받는 쪽의 영역이 겹치면 안 된다고 되어 있어요.

[그림 3] c언어 memmove 함수 설명

그런데, memmove는 그럴 필요가 없다고 덧붙이고 있습니다. 이는, 메모리 영역이 겹치더라도, 임시 배열에 복사해 놓고, 임시 배열로부터 dest로 복사하기 때문입니다. memcpy와 memmove의 차이점은 받는 쪽과 원본이 겹치는 경우, 즉 overlap이 되는 경우 처리가 제대로 되는지가 다릅니다. 이제 간단한 예제와 실용적인 예제를 몇 개 보도록 하겠습니다.


간단한 사용 예제

c언어 memcpy 함수와 memmove 함수의 사용법과, 실용 예제를 보여드릴게요.

[그림 4] 예제 1번 프로그램

먼저, 1번 프로그램입니다. target 배열에는 0, 1, … 99가 순서대로 저장되어 있습니다. 다음, 8번째 줄에서 memcpy로 target에 있는 것을 ori 배열에 옮기는데요. 몇 byte를 옮기나요? sizeof(int)에 100만큼 곱한 바이트만큼 옮겨요.

왜 굳이 4로 안 하고 sizeof(int)를 해 주었냐면요.

  • sizeof(int)는 int형 변수의 크기를 의미합니다.
  • target에는 int형 자료형이 연속적으로 저장되어 있어요.
  • int형 변수의 크기는 플랫폼에 따라서 달라질 수 있어요.

따라서, target의 1번째 원소부터 100번째 원소까지를 ori에 복사하기 위해, 3번째 인자로 sizeof(int)에 100을 곱한 값을 넘겨줬음을 보셔야 해요. sizeof는 상당히 많이 쓰일 테니 알아두면 좋아요.

고로 그림은 요래 그려집니다. 결과를 보겠습니다.

[그림 5] 1번 프로그램의 결과

결과를 보니, 0, 1, 2, 3, 4, 5 .. 순으로 ori에 잘 들어갔음을 볼 수 있어요.


배열 원소 추가, 삭제 구현하기

이제 실용적인 예제를 볼게요. 배열에서 원소를 특정 위치에 insert 하고 delete 하는 것을 생각해 봅시다.

[그림 6] 예제 2번 프로그램의 선언부

먼저, arr 배열이 있고, sz가 있어요. sz는 배열에 있는 모든 원소의 수를 의미해요. 다음, add_array와 del_array가 있는데요. add_array는 insert할 위치와 값을 받고, del_array는 삭제할 위치를 받아요. 다음, print_array는 현재 배열의 내용을 출력합니다.

[그림 7] 예제 2의 main 함수

이제 main 함수를 보겠습니다. 1, 2, 3, 4, 5, 6, 7을 배열에 넣고, 다음에 0번째 위치에 9를 넣습니다. 그러면, 9, 1, 2, 3, 4, 5, 6, 7이 될 겁니다. 이후에 3번째 위치에 있는 원소를 삭제하는데요. 최종적으로 결과는 9, 1, 2, 4, 5, 6, 7이 나와야 합니다.

[그림 8] print_array 함수

print_array 함수는 별 게 없습니다. 그냥 0번 원소부터 sz-1번 원소까지 돌면서 출력합니다. 이제 추가부터 생각해 보도록 합시다.

원소의 개수가 sz개인 배열에서, lo번째 위치에 원소를 추가한다고 하겠습니다. 그러면, lo번째부터, sz-1번째 원소까지 뒤로 1칸 밀어야 합니다. 그림으로 그리면 위와 같습니다. 원본은 arr + lo입니다. 복사 을 위치는 arr + lo + 1번 부터입니다.

얼마만큼 복사하나요? sz – lo개의 원소 크기 만큼이요. 이제, 남은 것. memmove 함수를 써야 할까요? memcpy를 써야 할까요? 보면, 복사받을 위치와 복사할 위치인 군청색과 노란색이 겹친 상황이지요? 따라서, memmove를 써야 해요.

뒤로 민 후에 lo번째 위치에 x를 넣으면 됩니다. 삭제할 때에는 어떻게 하면 될까요?

sz개의 원소가 있는 배열에서 lo번째를 삭제한다 할게요. 그러면 뒤에 있는 것을 앞으로 1칸 땡겨야 합니다. arr+lo+1번째에 있는 원소부터 끝까지를, arr+lo에 복사하면 됩니다. 원소 몇 개 복사했나요? sz-lo-1개 복사했어요. 역시 memmove 이용해 주면 되겠습니다.

[그림 9] add, del 함수

설명한 것을 그대로 코드로 옮긴 것입니다. 실행해 볼까요?

[그림 10] 실행 결과

실행 결과는 위와 같습니다.

Leave a Comment

12 + 18 =