C라이브러리에 접근하는 방법은 컴파일러마다 다르다.
일반적인 접근방법
1.라이브러리 함수들을 찾을 수 있는 몇개의 서로다른 장소가 있다. 예를 들어 getchar()는 일반적으로 stdio.h 파일에 매크로로 정의되어 있다. 그러나 strlen()은 일반적으로 string.h 라이브러리 파일에 들어 있다.
2.시스템이 다르면 이들 함수에 접근하는 방식이 다르다.
2-1.자동접근
함수를 사용하려면 함수의 함수형(function type)은 반드시 선언해야 한다. 이것을 위해 적절한 헤더파일을 포함시킨다.
ANSI C표준은 라이브러리 함수들을 계열별로 묶었다. 이제 각 계열은 그 계열의 함수 프로토 타입들을 가지고 있는 특정한 헤더 파일을 가진다.
2-2.파일 포함하기
특정 함수가 매크로로 정의되어 있다면, #include 지시자를 사용하여 그 정의가 들어 있는 파일을 포함시킬 수 있다. 일반적으로 비슷한 매크로들이 적당한 이름을 가진 하나의 헤더 파일에 옹기종기 모여있다. 예를들어, 문자의 특성을 결정하는 매크로들을 포함하고 있는 ctype.h 라는 헤더파일이 있다.
2-3.라이브러리 포함하기
컴파일 하거나 링크하는 단계에서, 사용자가 옵션을 지정해야 하는 경우가 있다. 표준 라이브러리에 자동으로 접근하는 시스템일지라도 자주 상용하지 않는 함수드릐 다른 라이브러리를 가질 수 있다. 이러한 라이브러리들은 컴파일 옵션을 명시적으로 지정하여 컴파일러에게 사용을 요청해야 한다. 라이브러리 옵션은 함수 코드를 어디에서 찾아야 하는지 시스템에게 알려준다.
stddef.h 파일이 size_t에 대한 typedef 또는 #define을 가지고 있다. stdio.h 를 포함하여 몇개의 다른 파일들이, stddef.h 파일을 포함함으로써 위 내용을 처리한다.
C는 상황에 따라 다른 데이터형을 가리킬 수 있는 일종의 범용 포인터로서 void 형을 가리키는 포인터를 사용한다. 형식 매개변수가 void 형을 가리키는 포인터 라면, 컴파일러는 데이터형 불일치를 일으키지 않고 적절한 데이터형을 선택한다.
ex)
size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
첫번째 인자에 구조체 포인터든 double형 포인터든 어떤 데이터형의 포인터형이든 들어갈 수 있다.
수학 라이브러리
math.h 헤더 파일은 수학관련 함수들에 대한 선언 또는 프로토 타입을 제공한다.
컴파일러 - 링커가 수학 라이브러리를 찾지 못할 것이다. Unix 시스템에서 사용자는 -lm 플래그를 사용하여 링커에게 수학 라이브러리를 찾으라고 지시해야 한다. -lm 플래그는 컴파일 명령 끝에 와야한다. 왜냐하면 컴파일러가 C파일을 컴파일 한 후에 linker가 등장하기 때문이다.
tgmath.h 라이브러리
math.h 함수는 float, double, long double 의 세가지형 각각에 대해 정의되는데, tgmath.h 파일은 double 버전과 같은 이름을 가진 자료형에 무관하게 동작하는(type-generic)매크로를 만든다.
범용 유틸리티 라이브러리
범용 유틸리티 라이브러리 난수 발생함수, 검색과 정렬함수, 변환 함수, 메모리 관리 함수등을 포함하여 정말 많은 함수들이 존재한다.
rand(), srand(), malloc(), free() 등의 함수들은 stdlib.h 헤더 파일에 있다.
atexit() 함수 - 프로그램이 종료될 때 실행되는 함수
atexit()는 함수 포인터(함수 이름)를 사용하는 함수이다. 이 함수를 사용하려면 exit()가 수행될 때 호출할 함수의 주소를 전달인자로 사용하면 된다.
함수 이름은 함수의 전달인자로 사용 될 때 함수의 주소로 동작한다.
main()이 종료될 때 exit()가 묵시적으로 호출된다.
exit()는 atexit()에 의해 지정된 함수들을 실행한 후, 모든 출력 스트림들을 비우고, 열려 있는 모든 스트림들을 닫는다. 그리고 표준 입출력 함수 tmpfile()의 호출에 의해 생성된 임시 파일들을 닫는다. 이후 exit()는 호스트 환경으로 제어를 리턴한다. 이때 호스트 환경에 종료 상태를 보고한다.
ex)
EXIT_FAILURE, EXIT_SUCCESS
재귀적이 아닌 main() 함수에 exit()함수를 사용하는 것은, 키워드 return을 사용하는 것과 효과가 동등하다. exit()는 main()이 아닌 다른 함수에서 사용될 때도 프로그램을 종료시킨다.
qsort() 함수
quick sort 방법은 효과적인 정렬 알고리즘이다. 이것은 커다란 배열들을 정렬하는데 효과가 탁월하다. 이 알고리즘은 원소 수준에 도달할 때 까지 배열들을 더 작은 크기로 계속 쪼갠다. 배열이 두 부분으로 쪼개지는데, 이때 한쪽 부분에 있는 모든 값들이 다른 한쪽 부분에 있는 값들보다 작다. 배열이 완전히 정렬될 때 까지 이 과정이 계속된다.
qsort()의 프로토 타입
void qsort(void * base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
첫번째 전달인자는 정렬할 배열의 시작 위치를 가리키는 포인터이다. void 형을 가리키는 포인터로 캐스트할 수 있는 어떤 데이터형을 가리키는 포인터도 허용한다. qsort()의 첫번째 실전달인자는 어떤 데이터형의 배열도 나타낼 수 있다.
두번째 전달인자는 정렬할 항목들의 개수이다. 즉 배열의 개수이다.
세번째 전달인자는 qsort()에게 데이터 객체의 크기를 명시적으로 알려주기 위함이다. 예를들어, double 형의 배열을 정렬한다면, 이 전달인자로 sizeof(double)를 사용한다.
마지막으로, qsort()는 정렬 순서를 결정하는데 사용되는 함수를 가리키는 포인터를 요구한다. 비교 함수는 비교할 두 항목을 각각 가리키는 두개의 포인터를 전달인자로 사용한다. 첫번째 항목이 두번째 항목보다 값이 크면 양의 정수를 리턴하고 첫번째 항목이 두번째 항목보다 작으면 음의 정수를 리턴한다. qsort()는 자신에게 주어진 다른 정보들로 부터 계산된 포인터 값들을 이 비교함수의 전달인자로 사용한다.
qsort()의 마지막 전달인자
int (*compar)(const void *, const void *)
이것은 이 마지막 전달인자가, int형 값을 리턴하고, const void 형을 각각 가리키는 두개의 포인터를 전달인자로 사용하는, 함수를 가리키는 포인터라는 것을 의미한다.
확인 라이브러리
assert.h 헤더 파일이 지원하는 확인(assert) 라이브러리는, 프로그램을 디버깅 하는 것을 돕기 위해 설계된 작은 라이브러리 이다.
assert() 라는 매크로는 전달인자로 정수 표현시글 사용한다. 표현식이 거짓(0이아닌 값)으로 평가되면, assert() 매크로는 표준에러 스트림(strerr)에 에러 메시지를 기록하고, abort() 함수를 호출하여 프로그램을 종료한다.
abort() 함수는 프로그램 비정상 종료(프로그램 중지)를 야기하고 호스트 환경에 제어를 리턴합니다.
exit() 함수와 마찬가지로 abort() 함수는 프로그램을 종료하기 전에 버퍼를 삭제하고 열린 파일을 닫습니다.
assert()는 어떤 조건들이 참이 되어야 하는 중요한 위치를 프로그램에서 찾아내고, 지시된 조건들 중 하나가 참이 아니면 asssert() 문을 사용하여 프로그램을 종료하는 것이다. assert() 가 프로그램을 종료시킬 때에는, 그것은 실패한 테스트, 그 테스트가 들어있는 파일의 이름, 라인번호를 표시한다.
assert() 매크로를 on 또는 off로 설정하는 메커니즘이 있다. 프로그램 버그들을 모두 제거했다고 생각한다면, 아래와 같이 정의하라.
#define NDEBUG
위 정의를 assert.h를 포함시킨곳 바로 앞에 넣고 프로그램을 다시 컴파일 하면 컴파일러는 파일에 들어 있는 모든 assert() 문들을 무력화 시킨다.
'Programming > C' 카테고리의 다른 글
구조체 연습문제 (0) | 2019.08.11 |
---|---|
파일 입출력 연습 (0) | 2019.07.23 |
인라인 함수 와 _Noreturn 함수 (0) | 2019.07.17 |
전처리기 지시자와 매크로 (0) | 2019.07.17 |
파일 포함 시키기 : #include (0) | 2019.07.17 |