Chapter 21. The Standard Library

지환·2022년 3월 3일
0
post-custom-banner

21.1 Using Library

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이다.

Restrictions on Names Used in the Library

Standard library를 include해서 사용할때 지켜야 할 rules이 있다.

  1. 해당 library에서 정의된 macro name을 다른 용도로 사용할 수 없다. (include한 경우)

  2. typedef로 정의된 name은 file level에서 또다시 정의할 수 없다. (include한 경우)
    (typedef names are subject to the same scope rules as variables, p.155)

  3. undersocre로 시작해서 바로 upper-case letter가 따라오는 Identifiers는 library에서 쓰려고 예약돼있다.
    따라서 프로그램에선 사용할 수 없다.

  4. underscore로 시작하는 identifiers는 filescope에서의 identifier나 tag로 사용되도록 예약돼있다. 따라서 함수내에서 선언하는게 아니라면 이런식의 identifier는 사용할 수 없다.

  5. standard library에서 external linkage를 가지는 모든 identifier는 예약돼있다.
    따라서 파일이 해당 library를 include하지 않더라도, 그 이름은 사용할 수 없다.

    위 모든 규칙이 강요되는건 아니지만, 따르지 않으면 portability를 잃을 수 있다.

위 이름에 관한 규칙은, 현재 있는 것과 충돌을 방지하기 위한 것도 있지만, 미래를 위해 예약해둔 경우도 있다.
완전한 설명은 standard에서 찾아보면 된다.(future library directions에 가면 있다고 함)
하나만 더 설명하자면 str로 시작하고 소문자가 따라오는 경우, <string.h>에서 사용하기위해 예약돼있다.

Functions Hidden by Macros

작은 함수를 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가 와야 인식되므로, 이렇게 괄호쳐두면 함수로 인식된다.


21.2 C89 Library Overview

<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
setjmplongjmp function을 제공한다.
setjmp 함수를 통해 특정 위치를 표시하고,
longjmp를 통해 해당 위치로 점프할 수 있다.
한 함수에서 다른 함수로 이동할 수도 있고, 일반적인 함수 return 매커니즘을 통과해버린다.
주로 프로그램 실행 중 발생하는 심각한 문제를 처리할때 사용한다.

<signal.h>

Signal Handling
interrupts나 run-time errors같은 exceptional conditions을 처리하는 함수를 제공한다.
signal 함수는 특정 signal이 발생할 경우 호출할 함수를 설정하고,
raise 함수는 특정 signal이 발생하도록 한다.

<stdarg.h>

Variable Arguments
printfscanf 같이 다양한 숫자의 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 하는 함수를 제공한다.


21.3 C99 Library Changes

  1. Additional headers
    9개의 추가 헤더
  2. Additional macros and functions
    이미 존재하는 헤더에도 추가로 functions과 macros 추가
  3. Enhanced versions of existing functions
    printf, scanf 등등 기능 추가

<complx.h>

Complex Arithmetic
complexI 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를 변환하는 함수를 제공한다.(대소문자변환)


21.4 The <stddef.h> Header: Common Definitions

자주 사용되는 types과 macros의 정의가 있다. (함수는 없음)

  • ptrdiff_t : 2개의 포인터에 뺄셈을 할때 나오는 결과의 type
  • size_t : sizeof operator의 return 값의 type
  • wchar_t : 지원가능한 모든 지역(나라)의 모든 characters를 표현하기 충분한 크기의 type

셋 다 integer type이다.
ptrdiff_t는 signed type,
size_t는 unsigned type,
wchar_t는 25.2에서 자세히..(보면 extended character set의 크기에 따라 달라지는 듯)

macro도 두개 정의한다.

  • NULL macro : null pointer
  • offsetof macro : typemember-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한다.


21.5 The <stdbool.h> Header (C99): Boolean Type and Values

4개의 macros를 정의한다.

  • bool : defined to be _Bool
  • true : defined to be 1
  • false : defined to be 0
  • __bool_true_false_are_defined : defined to be 1
    마지막 macro의 사용은 제한적인데, bool이나 true같은 걸 정의해서 사용하기 전에 preprocessing directive로 저 macro가 있는지 test 해 볼 수 있다.

Q&A

왜 책에서 "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에서 말한 문제는 거의 해결된다.

post-custom-banner

0개의 댓글