728x90
[이전 글]
[다음 글]
Part1 : Libc functions
아래의 함수들을 다시 구현하세요. 이 함수들은 외부 함수를 필요로 하지 않습니다 :
- isalpha, isdigit, isalnum, isascii, isprint
- bzero, memset, memcpy, memmove, memchr, memcmp
- strlen, strnstr, strlcpy, strlcat, strchr, strrchr, strncmp
- toupper, tolower, atoi
다음의 함수들은 외부 함수 malloc을 사용하여 구현하세요 :
- calloc, strdup
반응형
ft_bzero
void ft_bzero(void *s, size_t n)
{
size_t i;
unsigned char *str;
str = (unsigned char *)s;
i = 0;
while (i < n)
str[i++] = 0;
}
- s을 n크기만큼 0으로 초기화하는 함수이다.
- 이 함수는 더 이상 사용되지 않는다. memset을 사용한다.
- size_t : 이론상 가장 큰 사이즈의 unsigned 데이터 타입
ft_memset
void *ft_memset(void *ptr, int value, size_t len)
{
size_t i;
unsigned char v;
unsigned char *p;
i = 0;
v = (unsigned char)value;
p = (unsigned char *)ptr;
while (i < len)
p[i++] = v;
return (p);
}
- ptr 가 가리키는 메모리 주소부터 len 바이트만큼 value값을 채운다.
- int로 받는 value는 함수 내부에서 unsigned char로 자동 변경된다.
memset()과 bzero() 모두 unsigned char로 캐스팅하는 과정이 있다.
메모리에 접근할 때에는 signed char형이 아닌 unsigned char형을 사용해야 하는 이유
- unsigned char는 모든 bit를 투명하게 볼 수 있는 특성을 제공한다.
- 임의의 메모리에 바이트 단위로 접근해 값을 다룰 때에는 반드시 unsigned char를 사용해야 full portability를 얻을 수 있다.
- signed char 가 표현할 수 있는 값의 개수보다 unsigned char 가 표현할 수 있는 값의 개수가 많다
- 표준이 바이트 값에 접근해야 하는 경우나 문자에 접근해야 하는 경우 (예: mem(), str() 함수들) 에는 모두 unsigned char로 접근하도록 요구하고 있다.
ft_memcpy
void *ft_memcpy(void *dst, const void *src, size_t n)
{
size_t i;
unsigned char *dst_temp;
unsigned char *src_temp;
if (!dst && !src)
return (0);
dst_temp = (unsigned char *)dst;
src_temp = (unsigned char *)src;
i = 0;
while (i < n)
{
dst_temp[i] = src_temp[i];
i++;
}
return (dst);
}
- src가 가리키는 메모리 주소로부터 n바이트 크기(길이)만큼 dst메모리에 복사한다.
- 테스터에서 모두 dst, src 모두 null인 경우에는 따로 처리를 해서 null값을 리턴한다.
- 널 종료 문자(null terminating character)를 검사하지 않는다.(strcpy() 함수와의 차이점)
- 두 메모리 블록이 겹쳐져 있다면 memmove 함수를 이용해야 한다. (src의 원본 값이 이전 src로 바뀐 상태에서 복사를 해버리기 때문)
void *ft_memcpy(void *restrict dst, const void *restrict src, size_t n)
- !! restrict 포인터는 메모리 접근에 관련된 최적화 기능 (C99 표준)으로 42에서는 사용 불가능하다.
Restrict
- 알맞은 조건이 적용되면, 성능이 비약적으로 증가한다.
- 포인터가 하나만 가리키고 있다는 것을 컴파일러가 알면, 메모리 복사 없이 비트 연산자를 이용해 연산한다.
ft_memmove
void *ft_memmove(void *dest, const void *src, size_t n)
{
size_t i;
unsigned char *new_dest;
unsigned char *new_src;
if (dest == src || n == 0)
return (dest);
i = 0;
new_dest = (unsigned char *)dest;
new_src = (unsigned char *)src;
if (dest < src)
{
while (i < n)
{
new_dest[i] = new_src[i];
i++;
}
}
else
while (++i <= n)
new_dest[n - i] = new_src[n - i];
return (dest);
}
- src배열은 src와 dest메모리 영역과 겹치지 않는 메모리 영역부터 먼저 복사한다.
- dst < src : len크기(길이)만큼 src 메모리에서 dest로 복사한다.(memcpy와 동일하다)
- dst > src : src 마지막 바이트부터 dest + len에 복사한다.
https://hand-over.tistory.com/47 참고
ft_memchr
void *ft_memchr(const void *s, int c, size_t n)
{
size_t i;
unsigned char find;
unsigned char *new_s;
if (!s)
return (NULL);
find = (unsigned char)c;
new_s = (unsigned char *)s;
i = 0;
while (i < n)
{
if (new_s[i] == find)
return ((new_s + i));
i++;
}
return (0);
}
- s 주소에 접근하여 n만큼 탐색하여 c값을 찾는다.
- c를 찾으면 그 주소 값을 반환하고 못 찾으면 null을 반환한다.
ft_memcmp
int ft_memcmp(const void *b1, const void *b2, size_t n)
{
size_t i;
unsigned char *s1;
unsigned char *s2;
i = 0;
s1 = (unsigned char *)b1;
s2 = (unsigned char *)b2;
while (i < n)
{
if (s1[i] != s2[i])
return (s1[i] - s2[i]);
i++;
}
return (0);
}
- s1과 s2를 n바이트만큼 비교하는 함수이다.
- 두 포인터가 모두 0이거나 비교하는 길이가 0이면 0을 반환한다.
- 값이 다르면 그 값의 차이를 반환하고, 값이 같으면 0을 반환한다.
- strcmp와 같은 논리이나, (unsigned char *) 형을 사용한다는 차이가 있다.
728x90
반응형
'42 SEOUL > 0_Libft' 카테고리의 다른 글
[Libft] Part2 : Additional functions (0) | 2022.03.28 |
---|---|
[Libft] Part1 : strlen, strnstr, strlcpy, strlcat, strchr, strrchr, strncmp (0) | 2022.03.26 |
[Libft] Part1 : toupper, tolower, atoi (0) | 2022.03.26 |
[Libft] Part1 : isalpha, isdigit, isalnum, isascii, isprint (0) | 2022.03.25 |
[Libft] 프로젝트 소개 (0) | 2022.03.22 |
댓글