일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 42서울
- nginx
- 패킹
- 동적할당
- 포인터
- 자료형
- phpmyadmin
- else if
- jupyter 단축키
- 42Seoul
- iF
- 함수
- 42cursus
- docker
- libft
- C언어
- list
- 42
- vs코드 단축키
- While
- Double
- cout
- for
- python
- ft_server
- C++
- 구조체
- float
- 2차원배열
- Class
- Today
- Total
Developer
Part1 - Libc functions 본문
1. void 포인터 (void *)
- void 포인터는 주소 값을 가진다. 하지만 int형 포인터나 char 포인터처럼 역참조(*)를 할 수 없다. 물론 포인터 연산도 할 수 없다. 역참조나 포인터 연산을 하기 위해서는 자료형의 크기를 알아야 해당 자료형의 크기만큼 값을 참조하거나, 주소를 이동할 수 있기 때문이다.
- 하지만 자료형이 정해져 있지 않기 때문에 다양한 자료형의 포인터를 형변환을 통해 사용할 수 있다.
- 예를 들어 malloc의 경우 반환형이 void *이다. 그래서 사용할 때 char *a = (char *)malloc(sizeof(char) * n)과 같이 char *형으로 사용할 수 도 있고, int *a = (int *)malloc(sizeof(int) * n) 과 같이 int *형으로 사용할 수 있다.
- libft과제를 진행하다 보면 전달 인자로 void *변수가 들어오는 함수들이 존재하는데 형변환을 해서 사용해야한다. 보통 Byte단위로 포인터를 사용해야 하는 경우가 많으므로 unsigned char * 으로 형변환을 해서 사용해야 한다.
2. unsigned char로 형변환 해야하는 int형 전달 인자
- 과제를 진행하다 보면 1Byte로 사용할 거면 미리 1byte 자료형으로 주지 왜 굳이 int형으로 주는지 궁금할 때가 있다.
- 이러한 이유는 초창기 C언어의 함수 호출자에게 호출 유형이 무엇인지 알려주는 프로토타입이 없었고, 매개 변수로 전달된 모든 것을 int형 또는 int형의 배수로 표준화했기 때문이다. 더 자세한 내용은 아래의 주소 참고
- https://www.it-swarm.dev/ko/c++/%EB%AC%B8%EC%9E%90-%EB%8C%80%EC%8B%A0-c-%EB%AC%B8%EC%9E%90-%EB%A6%AC%ED%84%B0%EB%9F%B4%EC%9D%B4-int-%EC%9D%B8-%EC%9D%B4%EC%9C%A0%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C/958120519/
3. size_t
- unsigned(부호 없는) 정수 값을 가진다.
- 해당 시스템에서 가질 수 있는 가장 큰 값을 담을 수 있는 자료형
1. memset
-
Prototype
void *memset(void *b, int c, size_t n) -
함수 동작
= b 위치부터 n Byte만큼 c로 초기화해주는 함수
= b : 채우고 싶은 메모리의 시작 주소 (byte단위로 값을 채우기 때문에 unsigned char *형으로 형변환해 사용)
= c : 채우고자 하는 값 (byte단위로 값을 채우기 때문에 unsigned char형으로 형변환 해서 사용)
= n : 채우려는 메모리의 크기
= return : 첫 번째 전달인자(b)를 반환
-
memset의 경우 byte단위로 값을 채워 넣기 때문에 자료형의 크기가 1byte가 아닌 배열을 memset으로 초기화할 때 원하는 결과를 얻을 수 없으니 주의해야함.
2. bzero
-
Prototype
void bezro(void *s, size_t n) -
함수 동작
= s위치부터 n Byte만큼 0으로 초기화해주는 함수
= s : 채우고 싶은 메모리의 시작 주소
= n : 채우려는 메모리의 크기
3. memcpy
-
Prototype
void *memcpy(void *dst, const void *src, size_t n) -
함수 동작
= dst부터 n Byte만큼을 src위치에서 n Byte 만큼 복사
= dst : 복사를 수행할 위치
= src : 복사될 값이 들어있는 위치
= n : 복사를 수행할 byte -
memcpy의 경우 man을 살펴보면 dst와 src의 주소 값이 겹치지 않도록 사용자가 주의를 해야함. 즉 두 포인터의 주소값이 겹쳐도 memcpy함수는 그것을 생각하지 않고 단순히 n바이트만큼 복사만 수행
4. memccpy
-
Prototype
void *memccpy(void *dst, const void *src, int c, size_t n) -
함수 동작
= dst부터 n Byte만큼을 src위치에서 n Byte 만큼 복사하는데 만약 src에서 c를 만난다면 해당 c까지만 복사를 수행하고 종료
= dst : 복사를 수행할 위치
= src : 복사될 값이 들어있는 위치
= c : 복사 종료 조건을 비교할 문자
= n : 복사를 수행할 byte
= return : 만약 복사 중 c를 만났다면 c를 복사한 다음 주소를 반환하고, c를 만나지 못했다면 n byte만큼 복사를 한 뒤 NULL을 반환
5. memmove
-
Prototype
void *memmove(void *dst, const void *src, size_t len) -
함수 동작
= memcpy와 유사한 동작을 하지만 주소 값이 겹쳤을 때에도 정상적으로 복사가 수행되는 것을 보장
= dst : 복사를 수행할 위치
= src : 복사될 값이 들어있는 위치
= n : 복사를 수행할 byte
= return : 처음 들어온 dst를 반환
- dst와 src의 주소 값을 비교해서 앞에서부터 복사를 수행할지 뒤에서부터 복사를 수행할지 결정해
- 참고
위의 그림은 src의 위치가 dst + 2일 때를 나타낸 그림이다. 이러한 경우 src의 앞에서부터 복사를 수행
위의 그림은 뒤에서부터 복사를 수행해야 하는 경우이다. 만약 앞에서부터 복사를 한다면 src의 3번째(src[2])를 dst의 3번째(dst[2])에 넣을 때 src[2]의 값이 처음 함수에 들어왔을 때의 값이랑 달라져 있기 때문
6. memchr
-
Prototype
void *memchr(const void *s, int c, size_t n) -
함수 동작
= s위치부터 n byte 내에 문자 c가 있는지 찾는 함수
= return : c가 있다면 c가 위치하는 주소를 반환하고, 없다면 NULL을 반환
7. memcmp
-
Prototype
int memcmp(const void *s1, const void *s2, size_t n) -
함수 동작
= s1이 가리키는 n byte와 s2가 가리키는 n byte의 데이터를 비교
= return : 데이터가 같다면 0, s1이 더 크면 양수, s2가 더 크면 음수를 반환.
8. strlen
-
Prototype
int strlen(const char *s) -
함수 동작
= 문자열 s의 길이를 측정
= return : 문자열 s의 길이를 반환
9. strlcpy
-
Prototype
size_t strlcpy(char *dst, const char *src, size_t dstsize) -
함수 동작
= dst에 src의 문자들을 최대 dstsize만큼(널문자 포함) 복사
= strlcpy는 strcpy와 동작이 같지만 항상 dst의 맨 뒤에 NULL이 들어가는 것을 보장
= return : src의 길이를 반환 -
주의할 점
= dstsize는 size_t 자료형. 따라서 dstsize - 1과 같은 연산을 사용하면 언더플로우가 나서 매우 큰값이 될 수 있다..
= 최대 dstsize만큼 복사하는 것이지 무조건 dstsize만큼 복사를 수행하는것이 아니다. src의 길이도 확인을 해야된다.
10. strlcat
-
Prototype
size_t strlcat(char *dst, const char *src, size_t dstsize) -
함수 동작
= dst의 길이가 최대 dstsize가 되도록 dst 뒤에 src를 복사
= strcat와 동작이 같지만 dst의 맨 뒤에 NULL이 들어가는 것을 보장
= return : dst의 길이가 dstsize보다 크거나 같을 경우 dstsize + src의 길이를 반환
: 위의 경우가 아닌 경우 dst의 길이 + src의 길이를 반환 -
주의할 점
= strlcat함수에서 dstsize는 널문자를 포함해서 dst가 될 수 있는 최대 크기이다. 따라서 dstsize가 붙히기를 수행하기 전 dst보다 작다면 복사는 수행되지 않는다. 따라서 최소한 하나라도 src의 문자를 붙히기 위해서는 dstsize 값을 dst의 길이 + 1(널문자) + (복사하고 싶은 갯수) 로 한다.
= 반환값은 함수를 사용한 뒤 dst의 길이와 비교해 모두 copy가 수행되었는지 혹은 잘린것이 있는지 확인을 할 때 사용할 수 있다.
11. strchr
-
Prototype
char *strchr(const char *s, int c) -
함수 동작
= 문자열 s에서 문자 c를 찾는 함수
= return : 문자열 s에 c가 있다면 가장 처음 만나는 c의 위치를 반환, 없다면 NULL을 반환 -
주의할 점
= strchr함수의 경우 NULL문자까지 비교를 해줘야 한다. 따라서 다른 str함수처럼 문자열의 끝인 NULL을 만나면 종료하는 것이 아니라 해당 NULL까지 비교를 해주고 종료가 되어야한다.
12. strrchr
-
Prototype
char *strrchr(const char *s, int c) -
함수 동작
= 문자열 s에서 가장 뒤에있는 문자 c를 찾는 함수
= return : 문자열 s에 c가 있다면 가장 마지막에 있는 c의 위치를 반환, 없다면 NULL을 반환
= strchr과 유사한 동작 (뒤에서 부터 찾으면 됨)
13. strnstr
-
Prototype
char *ft_strnstr(const char *haystack, const char *needle, size_t len) -
함수 동작
= 문자열 haystack의 len길이 내에서 문자열 needle을 검색합니다.
= return : needle이 존재한다면 찾은 위치의 시작 주소를 반환, 없다면 NULL을 반환 -
주의할 점
= needle문자열 전체가 haystack의 len이내에 존재해야 한다.
14. strncmp
-
Prototype
int strncmp(const char *s1, const char *s2, size_t n ) -
함수 동작
= s1과 s2를 nbyte만큼 비교
= return : 데이터가 같다면 0, s1이 더 크면 양수, s2가 더 크면 음수를 반환 -
주의할 점
= 확장 아스키의 경우 (128 ~ 255)의 경우 char 형으로 비교하면 오버플로우가 발생하여 두 문자의 차이를 구했을 때 원하는 값을 구할 수 없다.
15. atoi
-
Prototype
int ft_atoi(const char *str) -
함수 동작
= 문자열 str을 정수형으로 변환
= 문자열의 앞에 존재하는 white space는 무시
= 부호는 + 혹은 - 단 하나만 올 수 있다.
= 숫자로 변환 중 다른 문자를 만난다면 해당 위치까지 변환한 정수를 반환
= return : 변환한 정수 반환 -
주의할 점
= 문자열의 길이가 long long int 의 최대 범위보다 크거나 최소 범위보다 작을 경우 반환값 확인
16. is.. functions
-
Prototype
int isalpha(int c)
int isdigit(int c)
int isalnum(int c)
int isascii(int c)
int isprint(int c) -
함수 동작
= 함수 이름이 곧 동작입니다.
= 문자 c가 알파벳이 맞는지, 숫자가 맞는지, 아스키 값이 맞는지 확인
= return : 맞다면 true(1) 틀리다면 false(0)을 반환
17. toupper, tolower
-
Prototype
int toupper(int c)
int tolower(int c) -
함수 동작
= 문자 c를 대, 소 문자로 출력
= return : 변환되거나 변환되지 않은 c를 반환(변환할 필요가 없는경우도 존재하므로)
18. calloc
-
Prototype
void *calloc(size_t count, size_t size) -
함수 동작
= size크기의 변수를 count만큼 저장 가능한 메모리를 할당한 후 0으로 초기화
= return : 할당한 메모리의 첫 주소를 반환, 할당에 실패할 경우 NULL반환
19. strdup
-
Prototype
=char *strdup(const char *str) -
함수 동작
= 문자열 str을 새로운 메모리(동적할당 한)에 복사
= return : 동적할당 후 str의 내용이 복사된 메모리의 첫 주소를 반환
'42seoul > Libft' 카테고리의 다른 글
Bonus Part (1) | 2020.09.07 |
---|---|
Part2 Additional functions (0) | 2020.08.17 |