c언어 memcpy 함수와 memmove 함수는 메모리에 있는 내용을 일정 byte 만큼, 메모리의 다른 공간으로 복사합니다.이 둘에 대한 것을, 이 글에서 한꺼번에 알아보겠습니다.
함수의 원형
두 함수는 모두 string.h에 속해 있습니다. memory.h에 속해 있는 것 같지만, 아닙니다. 이 점 주의하셔야 합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem1-1.png)
원형을 보면, 3개의 인자를 받고 있어요. 어느 위치에서 어느 위치로 얼마만큼 복사할 것인지를 넘겨주게 됩니다.
- dest
- 복사받을 위치를 의미합니다.
- src
- 원본 소스를 의미합니다.
- size
- 몇 바이트를 복사할 것인지 의미합니다.
문자열 복사할 때에는 memcpy, memmove 대신에 strcpy를 써야 합니다. 이는, 복사의 종료 조건이 다르기 때문입니다. 전자는 byte였다면, 후자는 널 문자를 만나면 종료합니다. 그런데 왜 이 두 함수가 별도로 있는 것일까요?
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem8-1.png)
먼저, memcpy의 추가 설명을 봅시다. src에서 dest로 복사하는데, 복사하는 쪽과 받는 쪽의 영역이 겹치면 안 된다고 되어 있어요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem9.png)
그런데, memmove는 그럴 필요가 없다고 덧붙이고 있습니다. 이는, 메모리 영역이 겹치더라도, 임시 배열에 복사해 놓고, 임시 배열로부터 dest로 복사하기 때문입니다. memcpy와 memmove의 차이점은 받는 쪽과 원본이 겹치는 경우, 즉 overlap이 되는 경우 처리가 제대로 되는지가 다릅니다. 이제 간단한 예제와 실용적인 예제를 몇 개 보도록 하겠습니다.
간단한 사용 예제
c언어 memcpy 함수와 memmove 함수의 사용법과, 실용 예제를 보여드릴게요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem2.png)
먼저, 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는 상당히 많이 쓰일 테니 알아두면 좋아요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem10.png)
고로 그림은 요래 그려집니다. 결과를 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem3.png)
결과를 보니, 0, 1, 2, 3, 4, 5 .. 순으로 ori에 잘 들어갔음을 볼 수 있어요.
배열 원소 추가, 삭제 구현하기
이제 실용적인 예제를 볼게요. 배열에서 원소를 특정 위치에 insert 하고 delete 하는 것을 생각해 봅시다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem11.png)
먼저, arr 배열이 있고, sz가 있어요. sz는 배열에 있는 모든 원소의 수를 의미해요. 다음, add_array와 del_array가 있는데요. add_array는 insert할 위치와 값을 받고, del_array는 삭제할 위치를 받아요. 다음, print_array는 현재 배열의 내용을 출력합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem12.png)
이제 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이 나와야 합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem14.png)
print_array 함수는 별 게 없습니다. 그냥 0번 원소부터 sz-1번 원소까지 돌면서 출력합니다. 이제 추가부터 생각해 보도록 합시다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem15.png)
원소의 개수가 sz개인 배열에서, lo번째 위치에 원소를 추가한다고 하겠습니다. 그러면, lo번째부터, sz-1번째 원소까지 뒤로 1칸 밀어야 합니다. 그림으로 그리면 위와 같습니다. 원본은 arr + lo입니다. 복사 을 위치는 arr + lo + 1번 부터입니다.
얼마만큼 복사하나요? sz – lo개의 원소 크기 만큼이요. 이제, 남은 것. memmove 함수를 써야 할까요? memcpy를 써야 할까요? 보면, 복사받을 위치와 복사할 위치인 군청색과 노란색이 겹친 상황이지요? 따라서, memmove를 써야 해요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem16.png)
뒤로 민 후에 lo번째 위치에 x를 넣으면 됩니다. 삭제할 때에는 어떻게 하면 될까요?
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem17.png)
sz개의 원소가 있는 배열에서 lo번째를 삭제한다 할게요. 그러면 뒤에 있는 것을 앞으로 1칸 땡겨야 합니다. arr+lo+1번째에 있는 원소부터 끝까지를, arr+lo에 복사하면 됩니다. 원소 몇 개 복사했나요? sz-lo-1개 복사했어요. 역시 memmove 이용해 주면 되겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem13.png)
설명한 것을 그대로 코드로 옮긴 것입니다. 실행해 볼까요?
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/mem18.png)
실행 결과는 위와 같습니다.