索引 / 001 JA
Cプログラミング言語 cover

コンピュータサイエンス

コンピュータサイエンス

Cプログラミング言語

Brian W. Kernighan; Dennis M. Ritchie

英語原題: The C Programming Language

関数、型、ポインタ、メモリ、移植可能なシステムコードを通してプログラミングの基礎を学ぶ簡潔な古典的入門書。

難易度レベル
中級
学術レベル
学部
C言語プログラミング言語ポインタメモリアルゴリズムシステムプログラミング

01 / 読書ガイド

読書ガイド

引用

Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall.

章の要約

第2版はコンパクトな本で(出版社の表示では288ページ、索引は263ページから始まる)、序文、序論、8つの章、3つの付録からなる。Cの設計者(Ritchie)とベル研究所の同僚が書いた本書は、Cを、本書の刊行時にまとめられつつあったANSI規格に沿って記述している。最初期の刷りの表紙には「Based on Draft-Proposed ANSI C」とあり、以後の刷りには赤い「ANSI C」の文字がある。序文は著者の狙いを述べている。Cは大きな言語ではなく大きな本では役に立たないので、第1版(1978年)の簡潔さを保つこと。ポインタのような中心的な機能の説明を改善すること。そして規則を述べるのではなく、完全でテスト済みのプログラムを読み、書き、改訂することを通じて教えることである。各章には番号付きの演習がある。

第1章:A Tutorial Introduction(チュートリアル入門)

言語の中心部分を素早く一巡する章で、読者ができるだけ早くプログラムを書き始められるようにすることを目的とする。はじめの一歩、変数と算術式、for文、記号定数、文字の入出力、配列、関数、値渡し、文字配列、外部変数とスコープを扱う。序論は、このチュートリアルがプログラミングの実用的な知識を前提としており、コンピュータやコンパイルや代入の意味は説明しないと明言している。

第2章:Types, Operators, and Expressions(型、演算子、式)

より形式的な扱いが始まる。変数名、データ型とサイズ、定数、宣言、算術演算子、関係演算子と論理演算子、型変換、インクリメントとデクリメント、ビット演算子、代入演算子、条件式、優先順位と評価順序を扱う。

第3章:Control Flow(制御フロー)

文とブロック、if-elseとelse-ifの連鎖、switch、whileとforのループ、do-while、breakとcontinue、gotoとラベルを扱う。出版社が公開しているこの章のサンプルは本書の書き方をよく示している。短く完結した関数(二分探索、数値と文字列の相互変換)のあとに、それを書き直したり拡張したりするよう求める演習が続く。

第4章:Functions and Program Structure(関数とプログラム構造)

関数と、プログラムを関数にどう分けて組み立てるかを扱う。整数以外を返す関数、外部変数、スコープ規則、ヘッダファイル、static変数とregister変数、ブロック構造、初期化、再帰、Cプリプロセッサである。序論によれば、この章は複数のソースファイルに分かれたプログラムも扱う。

第5章:Pointers and Arrays(ポインタと配列)

言語を扱う章の中でもっとも長く、序文が説明の改善を特に挙げている章である。ポインタとアドレス、関数の引数としてのポインタ、ポインタと配列の関係、アドレス演算、文字ポインタ、ポインタの配列とポインタへのポインタ、多次元配列、コマンドライン引数、関数へのポインタ、複雑な宣言を扱う。最後の複雑な宣言は、序文によれば、宣言を言葉に変換し、また逆に変換するプログラムによって説明される。

第6章:Structures(構造体)

構造体と関数での利用、構造体の配列、構造体へのポインタ、自己参照構造体(連結データ構造の基礎)、表探索の例、typedef、共用体、ビットフィールドを扱う。

第7章:Input and Output(入出力)

オペレーティングシステムへの移植可能なインターフェースとしての標準ライブラリを扱う。標準入出力、printfによる書式付き出力、可変長引数リスト、scanfによる書式付き入力、ファイルアクセス、stderrとexitによるエラー処理、行単位の入出力、その他の関数である。

第8章:The UNIX System Interface(UNIXシステムインターフェース)

CのプログラムがUNIXのシステムコールを直接使う方法を扱う。ファイル記述子、低水準のreadとwrite、open・creat・close・unlink、lseekによるランダムアクセスである。続いて三つのまとまった例がある。fopenとgetcの実装、ディレクトリを一覧表示するプログラム、記憶領域割り当て器である。序論は、この章は一部UNIX固有であるものの、標準ライブラリの一つの版がどのように実装されうるかも示していると述べている。

付録A〜C:Reference Manual(リファレンスマニュアル);Standard Library(標準ライブラリ);Summary of Changes(変更点のまとめ)

付録Aは、コンパイラ作成者ではなくプログラマーのために、ANSI規格の要点をより小さな紙幅で伝えるリファレンスマニュアルで、最後に文法を載せる。付録Bは標準ライブラリをヘッダごとに、stdio.hからlimits.hとfloat.hまでまとめる。付録Cは第1版の元の言語からの変更点を列挙する。

主要概念

第1〜3章:言語の中核

  • 関数プロトタイプ:引数の型を並べるANSI形式の宣言。序論はこれを、ほとんどのプログラマーにとってもっとも重要な変更と呼んでいる。
  • 型変換:式の中で異なる型の値を組み合わせるときの規則。
  • ビット演算子:整数の個々のビットに作用する演算子。
  • 構造化された制御フロー:if-else、switch、while、for、do-while、break、continue。

第4〜6章:プログラム構造、ポインタ、構造体

  • スコープと外部変数:プログラムのどの部分からある名前が見えるか。ソースファイルをまたいで共有される変数を含む。
  • プリプロセッサ:本来のコンパイルの前に行われるマクロ置換、ファイルの取り込み、条件付きコンパイル。
  • ポインタ演算:配列内のアドレスの計算と、ポインタと配列の密接な関係。
  • 自己参照構造体:同じ型の構造体へのポインタを含む構造体で、リストや木を作るのに使われる。

第7〜8章:ライブラリとシステム

  • 標準ライブラリ:入出力やその他のシステムアクセスを移植可能にする、ANSIが定めた関数とヘッダの集まり。
  • システムコール:オペレーティングシステムが提供するread、write、lseekなどの低水準の操作。
  • 記憶領域の割り当て:メモリを明示的に管理すること。記憶領域割り当て器の例で示される。

批判的分析

長所

  • 簡潔さと正確さ。 著者は、言語が小さいのだから本も短く保つことを目指しており、言語全体、標準ライブラリの要約、リファレンスマニュアルが300ページ未満に収まっている。出版社が引用するBjarne Stroustrupは、チュートリアルの章の一見軽やかな書きぶりと、マニュアルの切れ味を称賛している。
  • 完全なプログラムから学ぶ。 序文は、本文から直接テストされた完全で実際的なプログラムと、それを修正させる演習を強調している。著者は有用なアルゴリズムや、よいスタイルと健全な設計の原則を示すことも目指している。例のプログラムは出版社から章ごとのディレクトリに分けてダウンロードできる。
  • 言語の設計者による執筆。 リファレンスマニュアルと規格の説明はCを定義した当人たちによるもので、序論は言語の限界についても率直であり、優先順位の誤った演算子や改善の余地がある構文に触れている。
  • システムプログラミングへの橋渡し。 第8章は、ライブラリがシステムコールの上にどう載っているかを示し、記憶領域割り当て器で締めくくる。これにより言語が、オペレーティングシステムやライブラリの仕組みと結びつく。

短所

  • 最初のプログラミングの本ではない。 序文は、本書がプログラミングの入門書ではなく、変数、代入、ループ、関数に慣れていることを前提とすると明言している。初心者でもついていけるが、より経験のある人の助けがあるとよいとされる。
  • 1988年のANSI Cを記述している。 本書はCを1988年のANSI規格に沿って記述している。その後のC規格の改訂は扱われないので、読者は新しい機能や現在のライブラリの使い方を別の資料で学ぶ必要がある。
  • データ構造ではなく言語の本。 序論は、本書がデータ構造とアルゴリズムの参考書ではなく、選択を迫られたときには言語に集中したと述べている。
  • 正誤表と刷り。 Ritchieは刊行版の既知の誤りの一覧を公開しており、その多くは後の刷りで訂正されている。古い本を使う読者はそれを参照するべきである。

コースにおける位置づけ

この入門プログラミングのコースの他の本の多くは、プログラミングをしたことのない人のために書かれている。Matthesの Python Crash Course はPythonの中核を短い演習で教えたあと三つのプロジェクトに進む。Felleisenらの How to Design Programs は、学生とともに成長する教育用言語で体系的な設計方法を教える。Downeyの Think Python とGuttagの Introduction to Computation and Programming Using Python はPythonを通じて計算機科学を紹介する。KernighanとRitchieはそうした最初の授業を前提とし、読者をより低い層、すなわちメモリ、アドレス、ポインタ、そして高水準言語が隠しているオペレーティングシステムとのインターフェースへと導く。

AbelsonとSussmanの Structure and Interpretation of Computer Programs は逆の方向、すなわち抽象化、高階手続き、インタプリタへと向かう。両方を読むと、プログラミングの両端が見えてくる。小さな言語から抽象を積み上げることと、機械を直接管理することである。Pythonの本を一冊読み終えた学生は、次に本書を読むのによい位置にあり、計算機構成やオペレーティングシステムの授業と並行して読むのもよい。

本書の使い方

本書は、すでに何らかの言語でプログラミングができ、Cをきちんと学びたい学生、とりわけシステムプログラミング、組み込み、オペレーティングシステムの授業に進む学生に適している。

  • 第1章はキーボードの前で読む。 すべての例を入力して実行すること。言語を学ぶにはその言語でプログラムを書くことだ、というのが著者の考えである。
  • 中核: 第2〜6章を順に。第5章にもっとも時間をかけ、第6章に進む前に、小さなテストプログラムとメモリの図を使ってポインタと配列を理解する。
  • ライブラリとシステム: 実用的なプログラムには第7章が欠かせない。第8章は最初に読むときは省いてもよいが、システム系の授業を受ける学生には得るものが大きい。記憶領域割り当て器は一行ずつ検討する価値がある。
  • リファレンス: 付録AとBは通読するのではなく、調べるために手元に置く。

演習は必ず解くこと。演習は短く、例と密接に結びついており、多くは本文のプログラムを拡張するものである。現代のコンパイラで警告を有効にしてコンパイルし、出版社がダウンロード提供している例のプログラムとRitchieの正誤表を使って本文を確かめるとよい。後のC規格については、最新の参考資料で補うこと。