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개의 댓글

Powered by GraphCDN, the GraphQL CDN