C99까지 총 24개의 standard library가 있다.
Standard Library Headers (C99)
<assert.h>
, <inttypes.h>
, <signal.h>
, <stdlib.h>
, <complex.h>
, <iso646.h>
,
<stdarg.h>
, <string.h>
, <ctype.h>
, <limits.h>
, <stdbool.h>
, <tgmath.h>
,
<errno.h>
, <locale.h>
, <stddef.h>
, <time.h>
, <fenv.h>
, <math.h>
,
<stdint.h>
, <wchar.h>
, <float.h>
, <setjmp.h>
, <stdio.h>
, <wctype.h>
대부분 compiler는 이보다 더 확장된 library를 지원한다. (물론 그런건 표준이 아님)
standard header는 주로 function prototype, type definition, macro definition으로 이루어져있다.
#include
를 통해 가져오면 되고, 심지어 standard header를 한번 이상 include하는 것도 legal이다.
Standard library를 include해서 사용할때 지켜야 할 rules이 있다.
해당 library에서 정의된 macro name을 다른 용도로 사용할 수 없다. (include한 경우)
typedef
로 정의된 name은 file level에서 또다시 정의할 수 없다. (include한 경우)
(typedef names are subject to the same scope rules as variables, p.155)
undersocre로 시작해서 바로 upper-case letter가 따라오는 Identifiers는 library에서 쓰려고 예약돼있다.
따라서 프로그램에선 사용할 수 없다.
underscore로 시작하는 identifiers는 filescope에서의 identifier나 tag로 사용되도록 예약돼있다. 따라서 함수내에서 선언하는게 아니라면 이런식의 identifier는 사용할 수 없다.
standard library에서 external linkage를 가지는 모든 identifier는 예약돼있다.
따라서 파일이 해당 library를 include하지 않더라도, 그 이름은 사용할 수 없다.
위 모든 규칙이 강요되는건 아니지만, 따르지 않으면 portability를 잃을 수 있다.
위 이름에 관한 규칙은, 현재 있는 것과 충돌을 방지하기 위한 것도 있지만, 미래를 위해 예약해둔 경우도 있다.
완전한 설명은 standard에서 찾아보면 된다.(future library directions에 가면 있다고 함)
하나만 더 설명하자면 str
로 시작하고 소문자가 따라오는 경우, <string.h>
에서 사용하기위해 예약돼있다.
작은 함수를 parameterized macro로 대체하는 것은 흔한 일이다.
심지어 Standard library에서도 그런다.
C standard에서 header에 library function과 같은 이름의 macro 함수를 정의하는 것을 허용하고 있다.
(하지만 프로그래머가 두 함수 다 접근할 수 있도록 해야함)
따라서 library header에서 함수이름과 macro이름을 같게 선언하는건 흔한 일이다.
예를들어 <stdio.h>
의 gerchar
함수가 그렇다.
헤더파일을 보면,
int getchar(void);
의 prototype과
#define getchar() getc(stdin)
의 macro definition도 가지고 있다.
따라서 getchar()
를 사용하면 macro로 대체된다.(전처리때 대체되니까)
대게는 속도가 빠른 macro를 원하지만, 진짜 함수를 사용하고 싶을때도 있다.
그럴때는
(1) macro 정의를 #undef
로 지워버리면 된다.
#include <stdio.h>
#undef getchar
getchar
가 macro가 아니더라도 딱히 문제는 없다.
(2) 아니면 괄호()
를 이용해서 macro의 사용을 막을 수 있다.
ch = (getchar)();
왜냐하면 parameterized macro는 바로 다음에 (심지어 띄어쓰기도 없이) left parenthesis가 와야 인식되므로, 이렇게 괄호쳐두면 함수로 인식된다.
<assert.h>
Diagnostics
assert
macro만을 포함하고 있다. self-check를 통해 프로그램을 종료시키는 macro이다.
<ctype.h>
Character Handling
characters를 분류하고, 대소문자 변환하는 functions을 제공한다.
<errno.h>
Errors
library function 호출 이후 error가 발생했는지 test하기위한 lvalue인 errno
를 제공한다.
<float.h>
Characteristics of Floating Types
floating types의 범위나 정확도 같은 특징을 나타내는 macros를 제공한다.
<limits.h>
Sizes of Integer Types
최대최솟값 같은 Integer Types의 특징을 나타내는 macros를 제공한다.
<locale.h>
Localization
나라나 지역에 맞게 프로그램을 조정하도록 도와주는 functions을 제공한다.
숫자가 print되는 방식이나 화폐 기호, character set, date나 time의 표기방식 등을 정한다.
<math.h>
Mathematics
일반적인 mathematical functions을 제공한다.
trigonometric, hyperbolic, exponential, logarithmic, power, nearest integer, absolute vvalue, remainder functions 등...
<setjmp.h>
Nonlocal Jumps
setjmp
와 longjmp
function을 제공한다.
setjmp
함수를 통해 특정 위치를 표시하고,
longjmp
를 통해 해당 위치로 점프할 수 있다.
한 함수에서 다른 함수로 이동할 수도 있고, 일반적인 함수 return 매커니즘을 통과해버린다.
주로 프로그램 실행 중 발생하는 심각한 문제를 처리할때 사용한다.
<signal.h>
Signal Handling
interrupts나 run-time errors같은 exceptional conditions을 처리하는 함수를 제공한다.
signal
함수는 특정 signal이 발생할 경우 호출할 함수를 설정하고,
raise
함수는 특정 signal이 발생하도록 한다.
<stdarg.h>
Variable Arguments
printf
나 scanf
같이 다양한 숫자의 arguments를 받는 함수를 작성하는 tool을 제공한다.
<stddef.h>
Common Definitions
자주 사용되는 types이나 macros의 정의를 제공한다.
<stdio.h>
Input/Output
input/output 함수의 커다란 모음을 제공한다.
<stdlib.h>
General Utilities
특정 header에 맞지 않은 함수를 모은 "catchall header"이다.
string을 number로 바꾸고, pseudo-random number를 만들고, memory management task를 수행하고, OS와 소통하고, 검색과 정렬을 하고, multibyte characters와 wide characters 간의 변환을 수행하는 등의 함수를 제공한다.
<string.h>
String Handling
string을 다루는 각종 함수를 제공한다.
복사하고, 붙이고, 비교하고, 검색하고..
뿐만 아니라 특정 blocks of memory에 대해 기능하는 함수도 제공한다.
<time.h>
Date and Time
시간과 날짜에 관한 함수를 제공한다.
시간과 날짜를 정하고, 조정하고, formatting 하는 함수를 제공한다.
printf
, scanf
등등 기능 추가<complx.h>
Complex Arithmetic
complex
와 I
macros를 정의해 complex number를 잘 다루도록 함.
또한 complex numbers의 수학 계산을 도와주는 함수도 제공
<fenv.h>
Floating-Point Environment
floating-point status flags와 control modes에 접근할 수 도있도록 해준다.
전자를 활용하면 overflow가 일어났는지 flag를 test해서 알 수 있고,
후자를 활용하면 rounding을 어떻게 처리할지 정의할 수 있다.
<inttypes.h>
Format Conversion of Integer Types
<stdint.h>
에 정의된 integer types의 I/O format strings에 사용될 수 있는 macros를 정의한다.
<iso646.h>
Alternative Spellings
특정 operator를 나타내는 macros를 정의한다.
그러면 해당 operator가 local character set이 아닐때, 대응하는 macro를 사용함으로써 해결할 수 있다.
<stdbool.h>
Boolean Type and Values
bool
, true
, false
를 정의한다.
위 macro가 정의됐는지 test할 수 있는 macro도 정의한다.
<stdint.h>
Integer Types
Integer types을 명시된 범위로 정의하고, 관계되는 macro도 정의한다.(예를들면 최대 최소 값을 나타내는 macro)
특정 type의 integer constants를 만드는 parameterized macro도 정의한다.
<tgmath.h>
Type-Generic Math
"type-generic" macros는 arguments로 넘어논 놈들의 types을 감지하고, 적절한 <math.h>
나 <complex.h>
의 함수 호출을 대체한다.
(두 헤더 다 많은 수학 함수가 있음)
<wchar.h>
Extended Multibyte and Wide-charcter Utilites
wide-charcater I/O와 wide string manipulation에 관한 함수를 제공한다.
<wctype.h>
Wide-character Classification and Mapping Utilities
<ctype.h>
의 wide-character 버전이다.
분류하고, case를 변환하는 함수를 제공한다.(대소문자변환)
<stddef.h>
Header: Common Definitions자주 사용되는 types과 macros의 정의가 있다. (함수는 없음)
ptrdiff_t
: 2개의 포인터에 뺄셈을 할때 나오는 결과의 typesize_t
: sizeof
operator의 return 값의 typewchar_t
: 지원가능한 모든 지역(나라)의 모든 characters를 표현하기 충분한 크기의 type셋 다 integer type이다.
ptrdiff_t
는 signed type,
size_t
는 unsigned type,
wchar_t
는 25.2에서 자세히..(보면 extended character set의 크기에 따라 달라지는 듯)
macro도 두개 정의한다.
NULL
macro : null pointeroffsetof
macro : type 과 member-designator 두가지 arguments를 필요로 한다. structure의 시작점과 특정 member 사이의 bytes 수를 계산한다. 앞에서도 말했지만 structure는 저장할때 순서대로 들어가지만 "holes"에 의해 그 bytes는 달라질 수 있다.(자세한건 chapter 16 Q&A) 따라서 이 macro를 이용해서 hole을 계산하여 portable program을 만들 수 있다.offsetof
의 사용 예시를 하나 더 설명하자면,
구조체에서 일부분만 copy하고 싶을 때 fwrite
함수를 이용해서 sizeof(struct s)
bytes만큼 옮겨적는 대신, offsetof(struct s, c)
bytes만큼 옮겨 적을 수 있게 해준다.
마지막으로, 여기 나온 macros나 types이 여기에만 정의된 건 아니다.
예를들어 NULL
의 경우 <locale.h>
, <stdio.h>
, <stdlib.h>
, <string.h>
, <time.h>
, <wchar.h>
에도 정의돼있다.
따라서 <stddef.h>
는 몇몇 프로그램만 include한다.
<stdbool.h>
Header (C99): Boolean Type and Values4개의 macros를 정의한다.
bool
: defined to be _Bool
true
: defined to be 1false
: defined to be 0__bool_true_false_are_defined
: defined to be 1bool
이나 true
같은 걸 정의해서 사용하기 전에 preprocessing directive로 저 macro가 있는지 test 해 볼 수 있다.왜 책에서 "standard header file"이 아니라 "standard header"라는 용어를 쓰나?
C standard에 의하면, "standard header"가 꼭 file일 필요가 없기 때문이다.
대부분 compiler가 file로 구현하긴 하지만, compiler 자체에 built-in 돼있어도 상관없다.
14.3에서 parameterized macro를 사용했을 때 단점이 나왔었는데, standard 함수 정의할때 써도 문제 없는건가?
C standard에 의하면, library function을 대체하는 parameterized macro는
(1)must be fully protected by parentheses여야하고,
(2)must evaluate its arguments exactly once여아한다.
이 두가지가 보장되면 14.3에서 말한 문제는 거의 해결된다.