이 책을 읽는 법 — 수준별 학습 경로
이 책이 쓰여진 기준은 앞에서 뒤로 읽는 것이다. 장의 차례가 곧 설명의 차례이고, 뒤의 장은 앞의 장이 세워 둔 어휘와 그림 위에 선다. 그러니 이 책이 스스로 가정한 순서는 그것 하나다.
다만 읽는 사람의 사정은 저마다 다르다. 수준도, 지금 필요한 것도, 이 언어를 쓸 자리도 다르다. 그러니 자기 수준과 용도에 따라 취사선택하면 된다. 처음 배우는 자리라면 기준대로 따라오는 것이 편하고, 이미 C 를 쓰고 있다면 필요한 장과 부를 골라 읽어도 된다. 그 사이에도 여러 수준이 있다 — 다른 언어는 익숙한 사람, 오래전에 배운 것을 다시 세우려는 사람, 임베디드 쪽으로 갈 사람.
아래의 네 갈래는 그런 독자들이 고를 수 있도록 적어 둔 단축 경로다. 그대로 따르라는 것이 아니라, 자기 자리에 가까운 것을 골라 쓰면 된다.
★ 다만 어느 경로를 고르든 덜어 내지 말아야 할 자리가 있다. 제1부와 제2부다.
이 두 부가 이 책에서 가장 중요한 내용이다. 기계가 기억을 어떻게 다루는지, 수와 글자가 어떻게 표현되는지, 번역과 최적화가 무엇을 하는지 — C 의 나머지 전부가 이 두 부에서 다룬 사정 위에 서 있다. 포인터가 왜 그냥 숫자가 아닌지, 정수가 왜 감아 도는지, 컴파일러가 왜 내가 쓴 대로 하지 않는지 — 뒤에서 만날 물음들의 답이 이미 여기에 있다. 그래서 이 두 부를 온전히 아는 것과 아닌 것의 차이가, 뒤의 열한 부를 읽는 내내 벌어진다.
경험이 있는 독자라면 여기 실린 것의 상당 부분을 이미 알 것이다. 그렇더라도 빠뜨린 것이 없는지는 반드시 확인하고 넘어가시라. 훑어 읽되 각 장의 목표와 갈무리를 짚어, 처음 보는 것이나 「알고는 있었지만 왜 그런지는 몰랐던 것」이 나오면 그 장은 제대로 읽는다. 뒤에서 막히는 자리의 뿌리는 대개 이 두 부에서 비어 있던 한 칸이다.
★★ 그리고 무엇을 고르든 하나만 더 기억하면 된다 — 건너뛴 장은 「없는 것」이 아니라 「필요할 때 돌아올 곳」이다. 본문의 #chref 참조가 그 자리를 계속 가리킨다. 단축 경로로 한 바퀴를 돈 뒤에 기준의 순서로 다시 읽으면, 그때는 훨씬 빨리 읽히고 넘겼던 것들이 제자리를 찾는다.
길 ① — 프로그래밍이 처음이다#
이 길은 기준 그대로 — 이 책의 순서다. 골라 낼 것이 없으니, 걸음의 속도만 몇 마디 보탠다.
제1–2부는 코드가 거의 없는 열다섯 장이고, 여기서 지치면 남은 책을 못 읽는다. 이 두 부는 「이해」가 아니라 「낯익음」이 목표다 — 기억에 주소가 있다, 정수는 감긴다, 실수는 근사다, 이 셋만 남으면 충분하다. 나머지는 뒤에서 코드와 함께 다시 온다.
| 구간 | 무엇에 마음을 쓰나 |
|---|---|
| 1–15장 (제1–2부) | 낯익어지는 것이 목표. 외우지 않는다 |
| 16–26장 (제3–5부) | ★ 여기서부터 손으로 친다. 예제를 그대로 쳐 보고 한 줄씩 바꿔 본다 |
| 27–35장 (제6부) | 정수와 변환 — 이 책에서 처음 만나는 함정 지대 |
| 36–46장 (제7부) | 가장 가파른 구간. 급하면 여기서 한 번 쉬어 간다 |
| 47–54장 (제8–9부) | 구조체와 계약. 「왜 이렇게 정해졌나」가 들리기 시작한다 |
| 55–66장 (제10부) | 프로그램의 바깥 — 링크·이름·전처리기 |
| 67–89장 (제11부) | 읽기보다 찾아 쓰기. 통독하지 않아도 된다 |
| 90–100장 (제12부) | 실물 라이브러리로 앞의 규율을 다시 본다 |
| 101–105장 (제13부) | 실무의 자리와 다음 걸음 |
표 0.1 — 처음인 사람의 걸음
길 ② — 다른 언어는 안다, C 가 처음이다#
파이썬·자바스크립트·자바처럼 기억을 감춰 주는 언어를 써 온 사람의 길이다. 문법은 빨리 읽히지만, 이 책이 진짜로 주려는 것은 문법이 아니라 기억과 계약이다.
- 제1부와 제2부 전부 — 건너뛰지 않는다. 3–5장의 주소와 기억의 갈래가 이 언어의 세계관이고, 6–7장의 감김과 근사에서 다른 언어에서 안 겪던 사고가 나온다. 아는 대목은 빨리 넘기되, 빠뜨린 것이 없는지 확인하면서 지나간다.
- 16–26장 — 문법은 빠르게 훑는다.
- 36–46장 — ★ 천천히. 포인터·수명·소유가 이 길의 핵심이다.
- 53–54장 — 계약과 정의되지 않은 동작. 「런타임이 막아 주지 않는다」의 뜻을 여기서 정확히 안다.
- 66장 부터 — 필요할 때 찾아 쓴다.
건너뛰어도 되는 곳: 32–33장 의 제어 흐름 문법. 다만 switch 의 흘러내림(32장)만은 보고 지나간다 — 다른 언어와 다르다.
길 ③ — C 를 쓴 적 있다, 제대로 다시 하고 싶다#
가장 흔한 독자다. 「돌아가는 코드는 쓰는데 왜 그런지는 모른다」를 메우는 길이다.
★ 그래서 이 길은 제1부와 제2부를 먼저 훑는 것으로 시작한다. 「왜 그런지」의 답이 대부분 거기 있기 때문이다. 이미 아는 대목이 많을 테니 빨리 넘기되, 각 장의 목표와 갈무리를 짚어 빠뜨린 것이 없는지 확인한다. 아래 표의 물음들이 흐릿하게 느껴진다면 그 뿌리도 대개 이 두 부에 있다.
| 아마 흐릿할 것 | 가서 볼 곳 |
|---|---|
| 정수 승격과 통상 산술 변환 | 30장 + 부록 C |
| 배열은 왜 포인터가 아닌가 | 40–41장 |
수명·저장 기간·static 의 두 뜻 | 45·58장 |
const·volatile·restrict 가 실제로 무엇을 약속하나 | 27·53장 |
| 구조체의 패딩과 정렬 | 47–48장 |
| 정의되지 않은 동작이 왜 「그냥 크래시」가 아닌가 | 54장 |
| 링커가 실제로 하는 일 | 17·56·57장 |
| 함수 호출의 안쪽 | 62장 |
| C23 이 바꾼 것 | 부록 G |
표 0.2 — 다시 배우는 사람이 먼저 볼 곳
그다음 제12부를 읽는다 — 앞의 규율이 한 라이브러리 안에서 어떻게 함께 서는지를 보는 자리이고, 이 책에서 실무에 가장 가까운 부분이다.
길 ④ — 임베디드·시스템 쪽으로 간다#
기계에 가까운 자리로 갈 사람의 길이다. 제1–2부를 건너뛰지 않는다 — 다른 길에서는 배경인 것이 이 길에서는 본론이다.
- 2–5장 — 주소·정렬·기억의 갈래.
- 6–11장 — 표현과 인터럽트.
- 12–15장 — 캐시와 최적화, 그리고 추상 기계.
- 28–30장 — 폭과 변환. 좁은 기계에서 사고가 나는 자리다.
- 48·51장 — 비트 관용구와 배치·정렬. 레지스터를 다루는 문법이다.
- 49·57장 — 표현을 다시 읽는 법과 호출 규약.
- 81·85장 — 비동기와 원자성.
volatile의 진짜 쓰임이 여기 있다. - 88–89장 — 기억 배치와 할당자. 힙이 없는 자리를 포함해서.
- 104장 — 도구와 관행.
무엇을 읽지 않아도 되는가#
어느 길에서도, 처음 읽을 때 건너뛰어도 되는 것들을 적어 둔다. 없어서 막히는 자리가 아니라, 필요해질 때 찾아오면 되는 자리다.
- 제11부의 통독 — 라이브러리 장들은 조회표에 가깝다. 필요할 때 그 장으로 온다.
- 73–77장 — 로케일·와이드 문자·유니코드. 국제화를 만나기 전까지는 「이런 층이 있다」만 알면 된다.
- 82–83장 — 부속서 K 논쟁과 비지역 점프. 둘 다 권하지 않는 것을 왜 권하지 않는지 설명하는 장이다.
- 부록 E 의 문법 전문 — 읽는 것이 아니라 찾는 것이다.
반대로, 어느 길에서도 건너뛰지 말 것을 하나만 고르라면 54장 이다. 이 언어에서 가장 비싼 실수들이 전부 그 장에 모여 있다.