본문 바로가기

BackEnd/C

메모리 컨트롤 함수

반응형

배열 A에 저장된 값을 배열 B에 저장하기 위해서는 배열 요소 하나하나를 일일이 복사해야만 한다.


배열의 이름을 이용한 대입연산이 허용되지 않기 때문이다. 하지만 지금부터 소개하는 이 함수들을 활


용하면 배열에 저장된 데이터의 전부 또는 일부를 한방에 복사할 수 있다.

 

1. memmove - 언제나 사용가능 한 메모리 복사 함수


memmove는 memory와 move의 합성으로 만들어진 이름이다. 메모리에 저장된 데이터를 다른 영


역으로 복사하는 기능의 함수이다.(참고로 복사보다는 이동의 기능이 좀더 강조되었다)


1
2
3
4
#include <string.h>
void * memmove(void * dest, const void * src, size_t len);
//매개변수 dest로 전달된 주소 값이 그대로 반환된다.
 
cs

이 함수는 매개변수 src로 전달된 값을 시작주소로 하여 len 바이트를 읽어 들여서, 매개변수 dest


로 전달된 주소에 복사를 한다. 예제를 통해 확인해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    int i;
 
    int src1[5]={12345};
    int dest1[5];
 
    double src2[5]={1.12.23.34.45.5};
    double dest2[5];
 
    memmove((void*)dest1, (void*)src1, sizeof(src1));
    memmove((void*)dest2, (void*)src2, sizeof(src2));
 
    for(i=0; i<5; i++)
        printf("%2d %8.2f \n", dest1[i], dest2[i]);
 
    return 0;
}
cs

1
2
3
4
5
 1     1.10
 2     2.20
 3     3.30
 4     4.40
 5     5.50
cs


- 14,15행 : 각각 src1 과 src2에 저장된 값을 바이트 단위로 dest1과 dest2에 복사하고 있다. 결과


   적으로는 배열에 저장된 값을 단 한 줄로 복사하고 있는 것이다. 


- 18행 : 출력결과를 통해서 복사가 제대로 이뤄졌는지를 확인할 수 있다


- 여기서 한가지 주의해야 할 사항이 있다. 복사의 대상이 되는 메모리 공간(위 예제의 dest1, 


dest2)의 크기가 복사할 바이트의 수보다 작다면 문제가 발생하기 때문에 복사의 대상이 되는 메모


리 공간의 크기가 작게 할당되는 일이 없어야 한다.


2. memcpy : 제한된 상황에서의 메모리 복사! memmove보다 빠르다.


memcpy는 memory와 copy의 합성으로 만들어진 이름이다. 역시 메모리에 저장된 데이터를 다른 


영역으로 복사하는 기능을 제공한다. 하지만 memmove 함수보다는 제한적인 상황에서 쓰이면서 


빠르다는 차이점이 있다. 자세한것은 아래를 보자.


1
2
3
4
#include <string.h>
void * memcpy(void * restrict dest, const void * restrict src, size_t len);
//매개변수 dest로 전달된 주소 값이 그대로 반환된다.
 
cs


위 함수의 매개변수 선언을 보면 dest와 src가 restrict로 선언되었음을 관찰할 수 있다. 따라서 함수


가 호출되면서 dest와 src로 전달된 주소 값의 메모리는 각각 dest와 src로만 접근이 가능해야 한


다.  다음과 같은 상황에서는 이 함수를 호출할 수 없다.



- 잘못된 memcpy 함수의 사


위 그림에서의 함수 호출은 0x20번지에 저장된 데이터를 4바이트씩 뒤로 밀기 위한 것이다. 그래


서 memcpy 함수의 첫 번째 인자와 두 번째 인자로 각각 0x24와 0x20을 전달하였는데, 문제는 바


로 여기에 있다. 두 개의 포인터 값 0x24와 0x20을 통해서 접근하는 메모리 공간 중 총 16바이트


가 겹치기 때문이다. 이는 restrict로 선언된 포인터가 가리키는 메모리 영역은 해당 포인터로만 접


근이 허용되어야 한다는 규칙에 위배가 된다. 


이러한 경우에는 memcpy 함수가 아닌 memmove 함수를 호출해야만 원하는 결과를 보장받을 수 


있다. 반면에 다음과 같은 경우의 함수 호출이라면 memcpy 함수를 사용 함으로서 성능의 향상을 


기대할 수 있다.



- 제대로 된 memcpy 함수의 사용


위 그림의 경우에는 0x20번지에서부터 12바이트를 0x2c번지로 복사를 진행한다. 즉 두 개의 포인


터 값 0x20과 0x2c를 통해서 접근하는 메모리 영역이 겹치지 않는다. 따라서 이 경우에는


memmove 함수를 대신해서 memcpy 함수를 호출하는 것이 성능 향상에 도움이 된다.


3. memcpy가 memmove보다 빠른 이유


복사 원본과 복사 대상이 겹치는 경우의 복사는 겹치지 않는 경우의 복사보다 시간과 메모리를 더 


많이 요구한다. 뿐만 아니라 복사 원본과 복사 대상이 겹치는지 겹치지 않는지를 확인하는 것도 부


담되는 일이다. 이처럼 memmove 함수는 다양한 부담을 안고 동작하도록 디자인 되어있다. 반면 


복사 원본과 복사 대상이 겹치지 않는다는 확신이 있다면, 부담을 덜어 줄 수 있다. 때문에 그만큼 


고속으로 복사가 이뤄지도록 함수의 구현이 가능하다. 


반응형

'BackEnd > C' 카테고리의 다른 글

함수 포인터(Function Pointer)  (0) 2019.03.18
main 함수로의 문자열 전달  (0) 2019.03.16
volatile 과 restict  (0) 2019.03.15
포인터의 const 선언  (0) 2019.03.14
메모리 공간의 동적 할당  (1) 2019.03.14