[libft] 나만의 C라이브러리 만들기 Part 1

leocodms·2020년 12월 26일
0

42seoul

목록 보기
4/10

1.memset

#include "libft.h"

void		*ft_memset(void *b, int c, size_t len)
{
	unsigned int i;

	i = 0;
	while (i < len)
	{
		*((char *)b + i) = (unsigned char)c;
		i++;
	}
	return (b);
}
  • writes len bytes of value c (converted to an unsigned char) to the string b.
  • c를 unsigned char로 변형해서 n개 만큼 b문자열에 쓴다.
  • return : first argument. => void * b

void * : void pointer은 자료형이 정해지지 않은 포인터. 범용 포인터.
역참조 불가능!! -> 컴파일 에러
강제 형변환을 통해 역참조 가능 : *((char *)str)

메모리에 접근할 때 unsigned char을 사용하는 이유!

unsigned char 는 모든 bit 를 투명하게 볼 수 있는 특성을 제공.
즉, 다른 type 은 내부 비트의 일부를 값을 표현하기 위한 용도가 아닌
다른 용도로 사용할 수 있으나 unsigned char 는 이것이 허락되지 않는다.
따라서, 임의의 메모리에 바이트 단위로 접근해 값을 다룰 때에는 반드시
unsigned char 를 사용해야 full portability 를 얻을 수 있는 것이다.
또한, 그와 같은 이유로 signed char 가 표현할 수 있는 값의 개수보다
unsigned char 가 표현할 수 있는 값의 개수가 많다는 사실에도 유의할
필요가 있다.

2.bzero

void	ft_bzero(void *s, size_t n)
{
	unsigned int i;

	i = 0;
	while (i < n)
	{
		*((char *)s + i) = 0;
		i++;
	}
}
  • b의 위치부터 n개의 파이트 만큼 0(null)로 초기화 한다. 메모리를 0으로 초기화하는 역할.
  • return : void

3.memcpy

#include "libft.h"

void					*ft_memcpy(void *s1, const void *s2, size_t n)
{
	unsigned int		i;
	unsigned char		*dst;
	unsigned const char *str;

	if (s1 == 0 && s2 == 0)
		return (0);
	i = 0;
	dst = (unsigned char *)s1;
	str = (unsigned char *)s2;
	while (i < n)
	{
		*(dst + i) = *(str + i);
		i++;
	}
	return (dst);
}
  • src가 가리키는 곳 부터 n바이트 만큼을 dest가 가리키는 곳에 복사한다.
  • 특정 메모리 영역을 다른 메모리 영역으로 복사할 때 사용.
  • null terminating character(널 종료 문자)를 검사하지 않는다.
  • 오버플로우 문제를 방지하기 위해 dst 과 src 가 가리키는 배열의 크기는 반드시 n 바이트 이상이여야 하며, 서로 겹치면 안된다.(오버랩 되면 메모리가 오염되어 원하는대로 동작하지 않을 수 있다.)

4.memccpy

#include "libft.h"

void				*ft_memccpy(void *dst, const void *src, int c, size_t n)
{
	unsigned char	*dst2;
	unsigned char	*src2;

	dst2 = (unsigned char *)dst;
	src2 = (unsigned char *)src;
	while (n != 0)
	{
		*dst2 = *src2;
		if (*src2 == (unsigned char)c)
			return (dst2 + 1);
		dst2++;
		src2++;
		n--;
	}
	return (0);
}
  • n 바이트의 데이터를 dst에 복제한다. src에서 문자 c(unsigned char)를 만나면 c까지 복제하고 중단한다.
  • return : c를 만났다면, 복제된 dst변수의 다음 번지를 반환. 만나지 않았다면, n바이트를 복제하고 null 반환.

5.memmove

#include "libft.h"

void		*ft_memmove(void *dst, const void *src, size_t len)
{
	size_t	i;

	if (dst == 0 && src == 0)
		return (0);
	i = 0;
	if (dst < src)
		ft_memcpy(dst, src, len);
	else
		while (len--)
			*(unsigned char *)(dst + len) = *(unsigned char *)(src + len);
	return (dst);
}

메모리 영역 오버랩발생 가능성 있다!
1. 한 배열 안에서 복사를 수행할 때
2. 그러면서 src 시작 주소가 dest 시작 주소보다 앞에 있을 때
오버랩의 가능성이 생긴다.
해결 - 뒤에서부터 복사해주면 된다.

6.memchr

#include "libft.h"

void				*ft_memchr(const void *s, int c, size_t n)
{
	unsigned char	*s2;

	s2 = (unsigned char *)s;
	while (n--)
	{
		if (*s2 == (unsigned char)c)
			return ((void *)s2);
		s2++;
	}
	return (0);
}
  • string s의 첫 n바이트 중에서 처음으로 나타나는 (unsigned char)c의 주소를 리턴한다.
  • return : c와 일치하는 값이 있다면 그 주소를 반환. 없다면 null을 반환.
  • string 주소에 배열 방식으로 접근하면 반환값 형변환에 문제 생겨서 포인터 방식으로 접근했다.

7.memcmp

#include "libft.h"

int		ft_memcmp(const void *s1, const void *s2, size_t n)
{
	unsigned char *str1;
	unsigned char *str2;

	if (s1 == s2 || n == 0)
		return (0);
	str1 = (unsigned char *)s1;
	str2 = (unsigned char *)s2;
	while (n--)
	{
		if (*str1 != *str2)
			return (*str1 - *str2);
		if (n != 0)
		{
			str1++;
			str2++;
		}
	}
	return (0);
}
  • ptr1 이 가리키는 처음 num 바이트의 데이터와 ptr2 가 가리키는 처음 num 바이트의 데이터를 비교한다.
  • return : 일 두 메모리 블록이 정확히 같다면 0 을 리턴한다.
    만일 두 메모리 블록이 다를 경우, ptr1 과 ptr2 가 가리키는 메모리 블록에서 앞에서 부터 처음으로 다른 바이트를 살펴 보는데, 그 바이트를 unsigned char 로 해석하였을 때, 그 값이 ptr1 이 더 크면 0 보다 큰 값을, 아니면 0 보다 작은 값을 리턴한다.

8.strlen

#include "libft.h"

size_t		ft_strlen(const char *s)
{
	size_t i;

	i = 0;
	while (s[i])
		i++;
	return (i);
}

9.strlcpy

#include "stdlib.h"

size_t			ft_strlcpy(char *dest, const char *src, size_t dstsize)
{
	size_t		srclen;
	size_t		i;

	srclen = 0;
	while (src[srclen] != 0)
		srclen++;
	if (dstsize == 0)
		return (srclen);
	i = 0;
	while (src[i] && i < (dstsize - 1))
	{
		dest[i] = src[i];
		i++;
	}
	dest[i] = 0;
	return (srclen);
}
  • dstsize != 0 일때, dstsize - 1개의 char 복사
  • return : return the total length of the string they tried to create. => the length of src

10.strlcat

#include "libft.h"

size_t		ft_strlcat(char *dest, const char *src, size_t dstsize)
{
	size_t i;
	size_t destlen;
	size_t srclen;

	i = 0;
	destlen = ft_strlen(dest);
	srclen = ft_strlen(src);
	if (dstsize <= destlen)
		return (dstsize + srclen);
	while (src[i] && destlen + i + 1 < dstsize)
	{
		dest[destlen + i] = src[i];
		i++;
	}
	dest[destlen + i] = 0;
	return (destlen + srclen);
}
  • 최대 dstsize - strlen(dst) - 1개의 char을 dest에 붙인다.
  • return : return the total length of the string they tried to create. => destlen + srclen

11.strchr

**수정 전**
char		*ft_strchr(const char *s, int c)
{
	char	find;
	int		i;

	find = (unsigned char)c;
	i = 0;
	while (!s[i])
	{
		if (s[i] == find)
			return ((char *)s + i);
		i++;
	}
	if (s[i] == find)
		return ((char *)s + i);
	return (0);
}
**수정 후**
#include "libft.h"

char		*ft_strchr(const char *s, int c)
{
	int		i;

	i = 0;
	while (s[i])
	{
		if (s[i] == (char)c)
			return ((char *)&s[i]);
		i++;
	}
	if (c == 0)
		return ((char *)&s[i]);
	return (0);
}
  • 문자열에서 특정한 문자가 가장 먼저 나타나는 곳의 위치를 찾는다.
    이 때, 그 위치를 가리키는 포인터를 리턴한다. 이 때 마지막 NULL 문자도 C 문자열의 일부로 간주하기 때문에 이 함수는 문자열의 맨 끝 부분을 가리키는 포인터를 얻기 위해 사용할 수 도 있다.
  • return : char이 처음 나타난 위치(pointer). 문자열에 나타나지 않은 문자라면 Null 반환.

    예외처리
    if (c == 0)
    return ((char *)&s[i]);

12.strrchr

#include "libft.h"

char		*ft_strrchr(const char *s, int c)
{
	char	find;
	int		i;

	find = (unsigned int)c;
	i = ft_strlen(s);
	while (i > 0)
	{
		if (s[i] == find)
			return ((char *)s + i);
		i--;
	}
	if (s[i] == find)
		return ((char *)s);
	return (0);
}
  • strchr와 동일. 그러나 strrchr은 문자가 제일 마지막에 나타난 곳의 위치를 찾는다.
  • return : char이 마지막으로 나타난 위치(pointer). 문자열에 나타나지 않은 문자라면 Null 반환.

13.calloc

#include "libft.h"

void	*ft_calloc(size_t count, size_t size)
{
	void *mem;

	if (!(mem = malloc(count * size)))
		return (0);
	ft_bzero(mem, (count * size));
	return (mem);
}
  • size 크기의 변수를 nmemb개 만큼 저장할 수 있는 메모리 공간을 할당한다. 그리고 동적으로 할당한 메모리의 모든 비트를 0으로 설정한다.
  • malloc과의 차이점 -> https://bunhere.tistory.com/255

14.strdup

#include "libft.h"

char		*ft_strdup(const char *s1)
{
	int		i;
	int		len;
	char	*str;

	len = ft_strlen(s1);
	str = (char *)malloc(sizeof(char) * (len + 1));
	if (!str)
		return (NULL);
	i = 0;
	while (s1[i])
	{
		str[i] = s1[i];
		i++;
	}
	str[i] = 0;
	return (str);
}
  • 문자열 str 길이 + 1 크기를 malloc으로 할당 후 문자열 str을 복사한 후 반환한다.
  • 반환받은 메모리는 반드시 free를 통하여 메모리를 해제해야 한다.
  • return : str을 복사한 메모리 주소
profile
Backend Developer

0개의 댓글