ft_memccpy 구현

yeonjkim·2021년 5월 25일
0

42seoul-libft

목록 보기
36/43

1. ft_memccpy 용도

* ft_memccpy()는 void *dest, const void *src, int c, size_t n을 인자로 갖는다.

* src를 n byte만큼 dest에 복사하는데, 복사 도중 src에서 문자 c를 만나면 c까지 복사하고 복사를 종료한다.

* 복사한 dest변수에서 복사가 끝난 다음 메모리 주소를 return한다.

* 문자 c를 만나지 않았다면 NULL을 종료한다.

2. ft_memccpy 프로토타입

void	*ft_memccpy(void *dest, const void *src, int c, size_t n)
void *dest : 복사될 문자열의 주소
void *src : 복사할 문자열
int c : src에서 만나면 복사를 중단할 문자
size_t n : 복사할 바이트 크기

3. 구현 시 유의사항

  • c를 만나지 못했을 시에 NULL반환

  • c를 만났을 때에는 dest의 c다음 값을 가리키는 주소를 리턴함.
    즉 복제가 끝난 dest의 다음 번지(추가 복제의 용이성 위함)

<중요>

  • 검색할 문자 c는 int로 주어지기 때문에 unsigned char로 형변환하여 검색한다.
    --> char로 형변환하지 않는 이유는, 특정 아키텍쳐 cpu를 사용하는 환경에서는 unsigned char가 디폴트이다.
    이러한 환경에서 char을 사용했을 때 unsigned char로 바뀌어 적용된다.
    이렇듯 char을 이용했을 때 환경마다 다르게 동작할 수 있기 때문에 관례상 unsigned char을 이용한다.

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

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

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

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

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

  • src와 dest의 메모리 공간이 겹칠 경우, 동작이 정의되지 않는다. 겹치는 경우에는 memmove()를 이용한다.

4. 코드 구현

#include "libft.h"

void            *ft_memccpy(void *dest, const void *src, int c, size_t n)
{
        size_t  index;//n과 비교 위해 size_t type으로.
        int             flag;//src에서 c를 찾았는지
        unsigned char	*d;
        unsigned char	*s;
        
        d = (unsigned char *)(dest);
        s = (unsigned char *)(src);
        flag = 0;
        index = 0;
        while (index < n)//n바이트까지
        {
                if (s[index] == (unsigned char)(c))//s에서 c발견
                {
                        d[index] = s[index];//c까지 복제
                        index++;//index증가
                        flag = 1;
                        break ;
                }
                d[index] = s[index];//d에 s복제
                index++;
        }
        if (flag == 0)//c를 찾지 못함.
                return (0);
        else//c를 찾음.
                return (&d[index]);//d의 c다음번째 번지 반환.
}

5. 코드 구현 방법

(1) dest와 src를 보이드 포인터 연산하지 않기 위해 unsigned char *형으로 형변환해준다.
(2) index < n까지 복사와 비교를 한다.
(3) 만약 s가 c라면 c까지 복제한 후 flag를 1로 주고 break한다..
(4) s가 c가 아니라면 d에 s를 복제한다.
(5) 반복문이 종료되고 flag가 1이라면 0을 리턴
(6) flag가 0이라면 d의 현재 값의 주소를 반환한다.

0개의 댓글