Proven C Book←↑→

67 표준 라이브러리 한눈에 보기

먼저 알아야 할 것

66장 표준 라이브러리의 지형 · 표준 라이브러리의 성격

돌아보기

66장에서 표준 라이브러리가 “얇고 오래됐다”고 했고, 표준이 언어 문법만이 아니라 라이브러리 목록과 각 함수의 계약까지 못박는다고 했다. 그러면 헤더는 정확히 몇 개이고, 그 목록은 어떻게 늘어 왔는가?

답. C23 기준으로 서른한 개다. C89가 열다섯으로 시작했고, C95가 와이드 문자 관련 둘을, C99가 아홉을, C11이 다섯을, C23이 몇 개를 더했다. 늘어난 속도가 언어의 변화 속도와 거의 같다는 점이 이 목록의 성격을 말해 준다 — 한 번 들어오면 사실상 영원히 남고, 그래서 들이는 데 오래 걸린다. gets의 장례가 수십 년 걸린 이야기(44장)의 뒷면이다.

이 장의 필요성과 맥락

66장이 성격이었다면 이 장은 목록이다. 정독을 시작하기 전에 전체 표를 한 번 펴 두는 것은 길잡이 없이 스물두 장을 걷지 않기 위해서다. 어느 헤더가 어느 판에서 들어왔는지, 운영체제 없이도 쓸 수 있는 것은 무엇인지 — 이 두 축이 뒤의 모든 장에서 되풀이 쓰인다.

이 장이 끝나면

C 표준이 정한 헤더를 하나도 빠뜨리지 않고 표로 편다. 어느 헤더가 어느 판에서 들어왔는지, 운영체제 없이도 쓸 수 있는 것은 무엇인지, 그리고 이 부의 나머지 장들이 어떤 순서로 그 구역들을 걷는지까지. 66장의 지형도를 축척을 키워 다시 그리는 장이다.

이 장에서 답할 질문

  1. 이 중에 실제로 자주 쓰는 것은 몇 개인가?

67.1 자유 사용과 호스트 — 두 개의 세계#

표준은 구현을 두 갈래로 나눈다. 호스트 구현(hosted)은 운영체제 위에서 도는 보통의 환경이고, 자유 사용 구현(freestanding)은 운영체제가 없는 환경 — 펌웨어, 커널, 부트로더 — 이다.

둘의 차이가 곧 헤더 목록의 차이다. 자유 사용 구현이 반드시 받아들여야 하는 헤더는 다음 열이고(C11 까지는 아홉이었다), 나머지는 있어도 되고 없어도 된다 — 다만 C23 은 여기에 헤더의 일부를 더 얹었다. 표 다음에서 이어 본다.

헤더무엇비고
<float.h>실수 타입의 한계값만 정의
<limits.h>정수 타입의 한계값만 정의
<stdarg.h>가변 인자63장
<stdbool.h>boolC99. C23에서는 사실상 불필요
<stddef.h>size_t·NULL·offsetof기본 중의 기본
<stdint.h>고정 폭 정수C99
<stdalign.h>alignas·alignofC11. C23에서 키워드로
<stdnoreturn.h>noreturnC11. C23에서 폐기 예정
<iso646.h>and·or 같은 대체 철자C95
<stdbit.h>비트 조작C23에서 추가

표 67.1 — 표준 헤더 한눈에

C23이 이 목록을 늘렸다는 점을 눈여겨볼 만하다. 새로 들어온 <stdbit.h> 는 운영체제가 필요 없는 순수 계산이라 자유 사용 환경에서도 제공할 수 있고, 하는 일이(비트 세기) 임베디드에서 특히 요긴하기 때문이다. 목록이 자라는 방향이 “OS 없이도 되는 것”이라는 점도 이 구분의 성격을 보여 준다.

★ 이름이 비슷한 <stdckdint.h>(검사 산술, 86장)는 이 목록에 없다. C11 의 아홉에서 C23 이 더한 헤더는 <stdbit.h> 하나이고, 나머지 보탬은 헤더 전체가 아니라 다음 문단의 「일부만 요구하기」 쪽이다.

그리고 헤더 하나가 통째로 필수인 것과 그 안의 선언 일부만 필수인 것은 다르다. C23이 바로 그 두 번째 방식을 쓴다 — §4p7 은 위의 열 헤더에 더해 <string.h> 를 요구하되 여섯 함수(strcoll·strdup·strerror· strndup·strtok·strxfrm)를 뺐고, <stdlib.h> 에서는 memalignment 하나만 요구한다. 뺀 여섯을 보면 이유가 보인다 — 로캘에 기대거나(strcoll· strxfrm·strerror), 할당기가 필요하거나(strdup·strndup), 숨은 상태를 지니는(strtok) 것들이다. 곧 OS 없이 되지 않는 것만 덜어 낸 목록이다.

부동소수점도 조건부다. 구현이 __STDC_IEC_60559_BFP__ 나 __STDC_IEC_60559_DFP__ 를 정의하면 <fenv.h>·<math.h> 와 strto* 계열도 자유 사용에서 쓸 수 있어야 한다(§4p8).

이 목록이 짧다는 사실이 이 책 전체의 배경이다 — 임베디드에서는 printf도, malloc도 당연하지 않다(제12부의 프리스탠딩 이야기가 여기서 시작된다).

67.2 전체 목록#

표준이 정한 헤더 전부다. “판”은 그 헤더가 표준에 들어온 판이고, 이 책의 어느 장에서 다루는지도 함께 적었다 — 이 부 밖의 장을 가리키기도 한다.

헤더판무엇을 담는가어디서 다루는가
<assert.h>C89assert — 계약 위반을 잡는 진단80장
<complex.h>C99복소수 산술83장
<ctype.h>C89문자 분류·변환72장
<errno.h>C89오류 번호 전역80장
<fenv.h>C99부동소수점 환경(반올림·예외)78장
<float.h>C89실수 타입의 한계28장·78장
<inttypes.h>C99고정 폭 정수의 서식·변환부록 B·83장
<iso646.h>C95연산자의 대체 철자83장
<limits.h>C89정수 타입의 한계28장
<locale.h>C89로케일 설정73–74장
<math.h>C89수학 함수78장
<setjmp.h>C89비지역 점프82장
<signal.h>C89신호 처리81장
<stdalign.h>C11정렬 지정·질의87장
<stdarg.h>C89가변 인자63장
<stdatomic.h>C11원자적 연산85장
<stdbit.h>C23비트 조작(자릿수·회전 등)51장
<stdbool.h>C99bool·true·false87장
<stdckdint.h>C23넘침을 검사하는 산술54장·86장
<stddef.h>C89size_t·ptrdiff_t·NULL·offsetof27장
<stdint.h>C99고정 폭 정수 타입28장·83장
<stdio.h>C89스트림 입출력·파일56·69장
<stdlib.h>C89변환·난수·할당·정렬·프로그램 종료71장
<stdnoreturn.h>C11noreturn83장
<string.h>C89문자열·메모리 블록70장
<tgmath.h>C99타입 제네릭 수학 함수78장
<threads.h>C11스레드·뮤텍스·조건 변수84장
<time.h>C89시각과 달력79장
<uchar.h>C11UTF-16·UTF-32 문자 타입75장
<wchar.h>C95와이드 문자 입출력·문자열75–76장
<wctype.h>C95와이드 문자 분류72장

표 67.2 — 판별로 늘어난 헤더

문. 이 중에 실제로 자주 쓰는 것은 몇 개인가?

답. 대부분의 프로그램은 다섯 안팎으로 산다 — <stdio.h>, <stdlib.h>, <string.h>, <stdint.h>, 그리고 필요에 따라 <math.h>나 <time.h>. 나머지는 “있는 줄 알고 필요할 때 찾아 쓰는” 것들이다. 그래서 이 부의 목표도 암기가 아니라 전체 얼개를 머릿속에 두는 것이다 — 어디쯤에 무엇이 있는지, 그리고 어느 구역이 미끄러운지.

흔한 오해. “표준 라이브러리에 있으면 안전하고 이식성 있는 함수다”

표준에 있다는 것은 어디에나 있다는 뜻이지 안전하다는 뜻이 아니다. gets는 1989년 표준에 들어 있었고 2011년에야 삭제됐다(69장). strncpy는 이름과 달리 안전한 복사 함수가 아니며(70장), atoi는 실패를 알릴 방법이 아예 없다(71장). 심지어 같은 이름의 함수가 로케일에 따라 다르게 동작하기도 한다(72장). 표준 라이브러리를 쓴다는 것은 “검증된 것을 쓴다”가 아니라 “계약이 명시된 것을 쓴다”는 뜻이고, 그 계약을 읽는 일은 여전히 우리 몫이다.

실제 사례. 헤더 하나가 부른 사고 — <strings.h>는 표준이 아니다

이름이 비슷해 헷갈리는 자리가 있다. <string.h>는 표준이지만 <strings.h>(복수형)는 POSIX다. strcasecmp·bzero 같은 함수가 거기 있어서, 이것을 쓴 코드는 Windows에서 컴파일되지 않는다. 반대로 strlcpy·strlcat은 OpenBSD에서 나와 여러 유닉스로 퍼졌지만 표준이 아니었다 — C23에 와서야 비슷한 취지의 함수가 논의됐을 뿐이다. “많이 쓰이니 표준이겠지”라는 짐작이 이식성 사고의 흔한 시작이다.

복습 정리

기억할 것요지
헤더 수C23 기준 서른한 개. C89의 열다섯에서 자랐다
자유 사용운영체제 없이 보장되는 헤더는 열 개뿐(C11 의 아홉에 C23 이 <stdbit.h> 하나를 더했다)
들어오는 속도느리다. 나가는 속도는 더 느리다
표준 = 안전아니다. 표준 = 계약이 적혀 있다
<strings.h>표준이 아니다(POSIX). 이름에 속지 않는다

표 67.3 — 표준 라이브러리 지형 — 기억할 것

얼개를 폈으니 걷는다. 다음 두 장은 가장 많이 쓰고 가장 많이 미끄러지는 구역 — 스트림 입출력이다.