Proven C BookEnglish GitHub

1 배경설명

이 장의 필요성과 맥락

책의 첫 장이 문법이 아니라 배경인 이유가 있다. C 는 지금 배우기 시작하는 사람에게 가장 설명이 필요한 언어다 — 반세기를 살아남아 여전히 현역인데, 그동안 세상이 바뀐 만큼 「왜 이렇게 생겼는가」를 모르면 문법이 전부 임의의 규칙으로 보인다. 그래서 첫 자리에 언어의 처지와 이 책의 태도를 놓는다. 여기서 정한 읽는 법이 남은 아흔여섯 장의 계약서가 된다.

이 장이 끝나면

프로그래밍이 무엇인지, C가 어떤 언어이고 지금 어떤 처지에 있는지, 그리고 왜 하필 지금 새로운 C 입문서가 필요한지 알게 된다. 이 책이 어떤 방식으로 쓰였고 어떻게 읽으면 되는지도 여기서 정한다.

이 장에서 답할 질문

  1. 옛 표준의 코드가 그렇게 많다면, 옛 어법부터 배우는 것이 실용적이지 않은가?
  2. 그러면 차라리 Rust나 Zig부터 배우는 것이 낫지 않은가?
  3. 라이브러리를 홍보하는 책이라면, 내용이 그쪽으로 치우치지 않는가?

1.1 프로그래밍이란 무엇인가

컴퓨터는 시키는 일을 하는 기계다. 문제는 시키는 방법이다. 컴퓨터는 사람의 말을 알아듣지 못하고, 지독하게 단순한 지시를 순서대로 받을 때만 움직인다. 프로그래밍이란 우리가 원하는 일을 그 단순한 지시들의 목록으로 바꾸어 적는 일이고, 그 목록을 적는 약속된 표기법이 프로그래밍 언어다.

언어는 수백 가지가 있다. 그중 어떤 언어는 사람 쪽에 바짝 붙어 있어서 쓰기 편하고, 어떤 언어는 기계 쪽에 바짝 붙어 있어서 기계를 속속들이 다룰 수 있다. 이 책이 다루는 C는 후자의 대표다 — 반세기 동안 기계 쪽 자리를 지켜 온, 시스템의 언어다.

1.2 C는 어디에 있는가

C는 눈에 잘 띄지 않는다. 화려한 앱과 웹사이트의 얼굴에는 다른 언어들이 서 있다. 그러나 그 얼굴들 밑을 들추면 거의 어디에나 C가 있다.

실제 사례. 오늘 하루가 C 위에서 흘러간다

아침에 스마트폰 알람이 울린다 — 그 운영체제의 핵심(커널)은 C로 쓰여 있다. 메시지를 보내면 통신 모듈의 펌웨어가 움직인다 — C다. 웹을 열면 서버와 브라우저가 데이터를 주고받는다 — 그 암호화 라이브러리와 통신 도구(OpenSSL, curl)가 C다. 앱이 무언가를 저장한다 — 세계에서 가장 널리 깔린 데이터베이스 SQLite가 C다. 자동차의 제동 장치, 세탁기의 제어판, 심박 조율기 — 임베디드 기기의 대부분이 C다. 파이썬으로 인공 지능을 돌려도, 그 밑에서 실제 계산을 하는 엔진의 상당 부분이 C(와 그 주변 언어)로 되어 있다. C를 배운다는 것은 이 보이지 않는 층을 읽고 쓸 수 있게 된다는 뜻이다.

1.3 지금 C의 세계는 요동치고 있다

그런데 왜 “지금” 새 입문서인가. 오래된 언어라면 오래된 책으로 배워도 되지 않는가. 그렇지 않다 — 지금 C를 둘러싼 풍경은 조용해 보여도 크게 요동치는 중이고, 이 요동이 이 책의 출발점이다.

첫째, C 안에서 여러 시대가 병립하고 있다. C는 표준이라는 공식 규격으로 관리되는 언어이고, C89(1989), C99, C11, C17을 거쳐 최신판 C23까지 왔다. 문제는 옛 표준이 은퇴하지 않는다는 것이다. 산업 현장에는 C89 시절 관행 그대로의 코드가 여전히 산더미처럼 살아 있고, 많은 교재가 그 시절 어법으로 쓰여 있으며, 그 곁에서 C23은 boolnullptr 같은 새 어휘를 표준에 들였다. 같은 “C”라는 이름 아래 서른 해 넘는 시차의 방언들이 공존한다.

문. 옛 표준의 코드가 그렇게 많다면, 옛 어법부터 배우는 것이 실용적이지 않은가?

답. 읽는 것과 쓰는 것을 나누면 답이 선다. 옛 코드를 읽을 일은 언젠가 생긴다 — 그래서 이 책도 역사와 옛 어법의 사연을 곳곳에서 다룬다. 그러나 새로 쓰는 코드가 옛 어법일 이유는 없다. 새 표준은 옛 표준의 함정을 수십 년 치 실전 경험으로 메운 결과물이다. 처음 배우는 사람일수록 가장 안전해진 오늘의 어법으로 시작하는 것이 이득이고, 옛 어법은 “왜 저렇게 썼는지”를 아는 교양으로 충분하다.

둘째, 이웃 언어들이 C의 영역을 잠식하고 있다. 한 지붕에서 출발한 C++은 빠른 주기로 판을 거듭하며 거대한 언어가 됐다 — 표현력은 강력해 졌지만, 언어 전체를 아는 사람이 드물다는 말이 나올 만큼 덩치가 불었다. 다른 쪽에서는 새 세대의 시스템 언어들이 나타났다. Rust는 C가 오래 겪어 온 메모리 사고를 언어 차원에서 봉쇄하겠다는 약속으로, Zig는 “C를 계승하되 더 단순하고 정직하게”라는 구호로, 각각 C가 지키던 자리를 파고 들고 있다. 운영체제 커널에 Rust 코드가 들어가기 시작한 것은 상징적인 사건이다.

셋째, 그 압박 속에서 C 자신도 변화의 조짐을 보이고 있다. C23은 근래 가장 큰 폭의 개정이었고, 표준 위원회는 포인터의 규칙을 더 엄밀하게 다듬는 작업(프로버넌스)과 안전성 논의를 이어 가고 있다. C는 느리게 움직이는 언어지만, 방향은 분명하다 — 더 명확한 계약, 더 안전한 기본값 쪽이다.

흔한 오해. “C는 낡은 언어라서, 배워도 곧 쓸모없어진다”

그럴듯한 걱정이다 — 새 언어들이 저렇게 몰려오고 있으니까. 그러나 현실의 수치는 반대를 가리킨다. 위에서 본 것처럼 세상의 기반 시설이 C 위에 서 있고, 이 층은 교체 비용이 너무 커서 수십 년 단위로만 움직인다. 새 언어들조차 C와 대화하는 능력(C 인터페이스)을 생존 조건으로 갖추고 태어난다 — C는 시스템 세계의 공용어라서, Rust를 쓰든 Zig를 쓰든 결국 C를 읽고 이해해야 한다. 낡기는커녕, C는 이웃들이 늘어날수록 더 중요해지는 종류의 언어다.

문. 그러면 차라리 Rust나 Zig부터 배우는 것이 낫지 않은가?

답. 정직하게 답하면, 목적에 따라 다르다. 당장 안전한 응용 프로그램을 하나 만드는 것이 목표라면 다른 선택지도 좋다. 그러나 컴퓨터가 실제로 어떻게 움직이는지를 바닥부터 이해하는 것이 목표라면 C만 한 교재가 없다. C는 기계를 가장 얇게 감싼 언어라서, C를 배우는 과정이 곧 기계와 메모리와 컴파일러를 배우는 과정이 된다. 그리고 그 이해는 Rust로 가든 Zig로 가든 그대로 이고 갈 수 있는 밑천이다. 이 책은 그 밑천을 오늘의 어법으로 마련해 주는 책이다.

1.4 왜 이 책을 만들었나

이 요동치는 풍경이 이 책의 첫 번째 이유다. 여러 표준이 병립하고, 이웃 언어들이 경쟁을 걸어오고, C 자신이 변하고 있는 지금 — 옛 어법의 관성으로 쓰인 입문서가 아니라, 오늘의 C(C23)와 오늘의 관행에서 출발하는 입문서가 필요하다고 판단했다. 그래서 이 책은 목차부터 다시 짰다. 문법 항목을 순서대로 나열하는 대신, 컴퓨터라는 기계의 기본부터 시작해 개념이 필요해지는 순서대로 C를 만난다.

두 번째 이유는 밝혀 두는 것이 정직하겠다. 저자는 proven이라는 C 라이브러리를 만들어 공개하고 있다. proven은 C 프로그래밍에서 가장 사고가 잦은 기본기 — 문자열 다루기, 입력 처리, 수의 변환 같은 일 — 를 검증된 형태로 제공하는 것을 목표로 하는 라이브러리다. C의 유명한 함정들은 대부분 이 기본기 층에서 터지는데, 표준 라이브러리는 역사적 이유로 그 함정을 그대로 안고 있다. 이 책의 뒷부분(제7부부터)에서는 그 함정이 실제로 왜 위험한지 보인 다음, proven이 그것을 어떻게 막는지 예제의 기반으로 사용한다. 이 책은 그 라이브러리를 알리려는 목적도 겸해서 만들어졌다 — 다만 순서는 지킨다. 먼저 표준 C만으로 개념을 온전히 배우고, proven은 그 필요가 스스로 증명된 시점에 등장한다.

문. 라이브러리를 홍보하는 책이라면, 내용이 그쪽으로 치우치지 않는가?

답. 치우치지 않도록 구조로 막아 두었다. 이 책의 앞 30여 개 장은 proven을 한 줄도 쓰지 않는다 — 순수하게 컴퓨터의 기본과 표준 C만으로 진행된다. proven이 등장하는 것은 “왜 이런 도구가 필요한가”가 본문 속에서 스스로 드러난 뒤이고, 그때도 표준적인 방법을 먼저 보인 다음 비교로 제시한다. proven 없이도 이 책의 C 지식은 온전히 성립한다.

1.5 이 책을 읽는 법

이 책은 읽는 책이다. 당연한 말 같지만, 프로그래밍 책으로서는 드문 약속이다.

술술 읽히는 것을 목표로 삼았다. 그래서 연습문제도, “직접 해 보라”는 지시도 넣지 않았다. 컴퓨터 앞에 앉아 있지 않아도 된다 — 소파에서, 지하철에서, 그냥 소설처럼 앞에서 뒤로 읽으면 된다. 모든 코드는 지면 위에서 처음부터 끝까지 시연하고, 실행 결과까지 지면에 인쇄되어 있다. 그 실행 결과는 장식이 아니라 실제 결과다 — 이 책에 실린 모든 예제는 기계가 실제로 컴파일하고 실행해서 얻은 출력을 그대로 싣는다.

연습을 원한다면 다른 책이 낫다. 과제를 잘 설계하고 단계별로 풀려 주는 일은 기존의 좋은 C 입문서들이 훨씬 잘한다. 이 책이 맡은 자리는 그 옆이다 — 왜 그렇게 생겼는지를 읽어 나가는 쪽.

문답으로 진행한다. 본문 곳곳에서 방금 읽은 내용에 대해 독자가 품었을 법한 질문을 그 자리에서 묻고, 바로 답한다. 질문을 만난 순간 잠깐 스스로 답을 떠올려 보고 다음 줄을 읽으면 가장 좋지만, 그냥 내리읽어도 된다 — 문답 자체가 설명의 일부다.

외우게 하지 않는다. 기억할 가치가 있는 것은 뒤 장의 서두에서 “돌아 보기”라는 이름으로 다시 찾아온다. 이전 장의 내용을 조금 더 깊은 질문으로 다시 만나게 되는데, 이것이 이 책의 복습 장치다. 잊었어도 괜찮다 — 답이 바로 옆에 있다.

작은 장으로 빠르게 간다. 장 하나는 짧다. 한 번에 하나의 착상만 다루고 다음으로 넘어간다. 큰 주제는 여러 장에 걸쳐 나선처럼 여러 번, 매번 조금 더 깊게 지나간다. 한 장에서 모든 것을 말하지 않으니, 어딘가 궁금증이 남았다면 그것은 대개 의도된 것이다 — 몇 장 뒤에서 그 궁금증을 다시 만나게 된다.

이제 시작한다. 이 부의 남은 두 장은 앞으로 계속 쓰일 밑그림 둘을 깐다 — 프로그램이 기억을 어떤 구역으로 나눠 쓰는지(2장), 그리고 프로그램이 실행된다는 것이 무슨 일인지(3장)다. 둘 다 C 문법은 나오지 않는, 순전히 그림을 그리는 장이다.

그다음 부의 첫걸음은 C가 아니라 컴퓨터 그 자체다 — C가 왜 이렇게 생겼는지는, C가 태어난 기계를 보아야 이해되기 때문이다.