ft_memmove 구현

yeonjkim·2021년 5월 26일
0

42seoul-libft

목록 보기
41/43

1. ft_memmove 용도

* src를 num byte만큼 dest에 옮기는 함수.

* memcpy와는 다르게 인접한 메모리에서도 옮길 수 있게 한다.

2. ft_memmove 프로토타입

void	*ft_memmove(void *dest, const void *src, size_t num)
void *dest : 복사할 문자열의 주소
const void *src : 복사될 문자열의 주소
size_t num : 복사할 바이트 수

3. 구현 시 유의사항

  • src와 dest가 둘 다 NULL일 때, NULL(dest)값을 반환.

  • dest와 src의 주소를 비교하여 연산한다.
    --> dest < src라면 뒤에서부터 복사해야 제대로 복사된다.
    앞에서부터 복사하면 '맨 앞의 값'만 복사되기 때문에 뒤에서부터 복사해야 한다.
    --> dest >= src라면 앞에서부터 복사해야 제대로 복사된다.
    뒤에서부터 복사하면 '맨 뒤의 값'만 복사되기 때문에 앞에서부터 복사해야 한다.

ex) 1 2 3 4 5 를 1 1 2 3 4 로 복사하고 싶다.

즉 dest의 주소가 index 1번이고, src의 주소가 index 0번이기 때문에 dest > src이다.
<1>
앞에서부터 복사하면 1 1 1 1 1로 복사된다.
순서 ) 1 2 3 4 5 -> 1 1 3 4 5 -> 1 1 1 4 5 -> 1 1 1 1 5 -> 1 1 1 1 1
<2>
뒤에서부터 복사하면 1 1 2 3 4로 복사된다.
순서 ) 1 2 3 4 5 -> 1 2 3 4 4 -> 1 2 3 3 4 -> 1 2 2 3 4 -> 1 1 2 3 4

즉 뒤에서부터 복사해야 한다.

ex ) 1 2 3 4 5를 2 3 4 5 5 로 복사하고 싶다.

즉 dest의 주소가 index 0번이고, src의 주소가 index 1번이기 때문에 dest < src이다.
<1>
앞에서부터 복사하면 2 3 4 5 5로 복사된다.
순서 ) 1 2 3 4 5 -> 2 2 3 4 5 -> 2 3 3 4 5 -> 2 3 4 4 5 -> 2 3 4 5 5
<2>
뒤에서부터 복사하면 5 5 5 5 5로 복사된다.
순서 ) 1 2 3 4 5 -> 1 2 3 5 5 -> 1 2 5 5 5 -> 1 5 5 5 5 -> 5 5 5 5 5

즉 앞에서부터 복사해야 한다.

<중요>

  • dest와 src를 unsigned char *로 형변환해야 한다.

    --> unsigned char모든 bit를 투명하게 볼 수 있는 특성을 제공한다.
    즉 다른 type은 내부 비트의 일부를 값을 표현하기 위한 용도가 아닌 다른 용도로 사용할 수 있으나 unsigned char는 이것이 허락되지 않아 mem함수, str함수에서는 unsigned char을 이용한다.

또한 메모리 주소의 경우 부호 있는 정수 타입을 쓰면 안된다.

  • void 포인터 연산 시 unsigned char 포인터를 이용한다.
    --> void 포인터 연산은 호환성을 위해 사용하지 않는 것이 좋다. 메모리 주소에 부호 있는 정수 타입을 쓰면 올바르게 동작하지 않기 때문에 비부호로 처리해야 한다.

    void 포인터의 경우 음수를 저장할 때 2의 보수 형태로 저장하게 된다. 단순히 부호 여부가 아닌 데이터를 저장하는 방식이 달라진다고 한다.
    참고 : 링크텍스트

4. 코드 구현

#include "libft.h"

void            *ft_memmove(void *dest, const void *src, size_t num)
{
        size_t                  index;

        if (!src && !dest)
                return (NULL);
        index = 0;
        if ((unsigned char *)dest < (unsigned char *)src)
        {
                while (index < num)
                {
                        ((unsigned char *)dest)[index] = ((unsigned char *)src)[index];
                        index++;
                }
        }
        else
        {
                while (index < num)
                {
                        ((unsigned char *)dest)[num - 1 - index] =
                        ((unsigned char *)src)[num - 1 - index];
                        index++;
                }
        }
        return ((unsigned char *)dest);
}

5. 코드 구현 방법

(1) src와 dest모두 NULL이면 복사할 필요가 없으므로 NULL(dest)를 반환한다.
(2) dest와 src를 unsigned char *로 변환한 주소값을 비교한다.
(3) dest가 src보다 작으면 앞에서부터 복사한다.
(4) dest가 src보다 크면 뒤에서부터 복사한다.
(5) dest를 반환한다.

0개의 댓글