出版社より献本御礼。

やってくれたのは、やはり結局 O'Reillyだったか。

404 Blog Not Found:(弘法も筆の誤り||まろび出た馬脚)? - 書評 - しろうとクマくんとC言語の授業
その意味で、今もってK&Rを超えるC本というのは、「初心者」まで含めても今なお存在しないようだ。C99も出て久しいし、そろそろ出てもいいと思うのだが。

本書「Head First C」は、今まで私が出会ったC言語に関する本の中で最良の一冊。「入門」でなくて「本」。それくらいよくできている。もちろんO'ReillyのHead Firstシリーズだけあって、位置づけとしては入門なのだけど、なかなかどうしてベテランも読み返すべきことがしっかり書いてある。

まず、ポインターというものに関してごまかさずにきっちり書いてある。「しろうとクマくんとC言語の授業」は論外にせよ、ポインターというものを学ぶにあたっては「K&R」もあてにならない。なにしろあれは、すでにポインターとは何なのかを知っている読者に向かって書かれているからだ。ary[42]42[ary]の同一性まできっちり説明しているなんて、とても入門書とは思えない。いや、本来入門書でやっておくべきだったか。

次に、例題の選択。awkぐらいしかなかった四半世紀前ならとにかく、スクリプト言語がよりどりみどりな現在、C入門にとって言語そのものの解説より難しいのはむしろこれではないか。四半世紀前と現代の一番の違いがここにある。かつてCで書くしかなかったものの大部分は、他の言語で書く方がずっと早く書けるし、それどころか(手練たちがさんざん手を入れてきたライブラリーにアクセスする分、素人が見よう見まねで書くより)速い場合でさえ珍しくない昨今、「Cで書く理由」は「Cで書く手法」よりも切実な問題だと思われる。Arduino、その手があったか!

それでは、現代人はそもそもCを学ぶ必要があるのか?

これに関しては、過去に何度か触れている。

目下の rule of thumbは、こんな感じ。

  1. いきなりCで書くな -- それは今日日「早すぎる最適化
  2. 書くなら手を抜くな -- Si vis pacem, para bellum

Perlが普及し出した頃だろうか。Cを知らなくてもハッカーを名乗れるようになったのは。しかしCでなければハックできない対象は未だ多い。カーネル、デバイス、プログラミング言語... Java や C++ が C の代わりにならないことが明らかになった今ほど、Cのきちんとした入門書が求められている時代はなかったかも知れない。K&Rは不朽の名著ではあるけれど、しかしCの怖さまでは伝えてくれない。バッファーオヴァーフローにメモリーリーク…同書からCをはじめるのは、現代から見れば安全面への配慮なしに柔道を必須化するのに似た暴挙に感じられてならない。

これからCをはじめるみなさん。頼むから、後生だから本書からお願いします。

Dan the More Frequent C Programmer than I like to be.

目次 - O'Reilly Japan - Head First C より
序章
この本を読むのにふさわしい人は?
あなたがどう思っているかわかっています
メタ認知
脳を思い通りにさせるためにできること
初めに読んでね
テクニカルレビューチーム
謝辞
1章 Cを始める
Cは小規模で高速なプログラムのための言語
でも、完全な Cプログラムはどんなの?
でも、どうやってプログラムを実行するの?
2種類のコマンド
ここまでのコード
カードカウント? Cで?
ブール値は等価条件以外にもある……
現時点でコードはどうなっている?
スイッチに切り換える
一度だけでは不十分なこともある……
ループは同じ構造になることが多い……
中断するためには breakを使う……
Cツールボックス
2章 メモリとポインタ
Cコードにはポインタがある
メモリに踏み込む
ポインタを携えて出航する
変数へのポインタを渡すようにする
メモリポインタの利用
どのようにして関数に文字列を渡すの?
配列変数はポインタに似ている……
コードの実行時にコンピュータが考えること
しかし、配列変数は完全なポインタではない
なぜ配列は0から始まるの?
ポインタはなぜ型を持つの?
データ入力でのポインタの利用
scanf()には注意
fgets()がscanf()の代わりになる
文字列リテラルは決して書き換えられない
文字列を変更する場合はコピーする
メモリの暗記
Cツールボックス
2.5章文字列
フランクを探して
配列の配列を作成する
検索テキストを含む文字列を見つける
strstr()関数の使用
おさらいの時間
配列の配列とポインタの配列の比較
Cツールボックス
3章 小さなツールの作成
小さなツールは大きな問題を解決できる
プログラムが行うべき動作
でも、ファイルを使っていない……
リダイレクトを利用しよう
標準エラーとは
デフォルトでは、標準エラーは画面に送られる
fprintf()はデータストリームへ出力する
fprintf()を使ってコードを書き換えよう
小さなツールは柔軟性がある
geo2jsonツールを変更しない
異なるタスクには異なるツールが必要
入力と出力をパイプでつなぐ
bermudaツール
でも、複数のファイルに出力したい場合はどうなるの?
独自のデータストリームを使う
main()には別の使い方がある
ライブラリに仕事をしてもらう
Cツールボックス
4章 複数のソースファイルの使用
すぐわかるデータ型入門
小さなものに大きなものを入れてはいけない
整数をfloatに格納する
弱ったな……失業中の俳優だ……
コードがどうなったのか見てみよう
コンパイラは驚きたくない
定義から宣言を分離する
最初のヘッダファイルの作成
共通機能がある場合は……
コードを別のファイルに分割できる
コンパイルの舞台裏
共有コードには独自のヘッダファイルが必要
そんなに難しいことなの?
すべてのファイルを再コンパイルしない
まず、ソースをオブジェクトファイルにコンパイルする
ファイルの管理は難しい
makeツールでビルドを自動化する
makeの動作方法
コードに関することはmakefileを使ってmakeに知らせる
発射!
Cツールボックス
Cラボ1 Arduino
5章 構造体、共用体、ビットフィールド
多くのデータを扱わなければいけないこともある
オフィスでの会話
構造体を使って独自の構造化データ型を作成する
魚(fish)を渡す
「.」演算子を使って構造体のフィールドを読み取る
構造体を別の構造体に含められる?
構造体はどのように書き換えるの?
このコードは亀のクローンを作っている
構造体へのポインタが必要
(*t).ageと*t.age
同じ種類のものに異なる型のデータが必要な場合もある
共用体はメモリ空間を再利用できる
共用体はどのように使うの?
enum変数はシンボルを格納する
ビットレベルで制御したい場合もある
ビットフィールドは任意のビット数を格納する
Cツールボックス
6章 データ構造と動的メモリ
柔軟な記憶領域が必要か?
連結リストはデータの連鎖のようなもの
連結リストは挿入が可能
再帰構造体を作成する
Cで島を作成する……
リストへの値の挿入
動的記憶領域にはヒープを使う
使い終わったらメモリを返す
malloc()でメモリを要求する……
strdup()関数を使ってコードを修正しよう
使い終わったらメモリを解放する
SPIESシステムの概要
ソフトウェア科学捜査:valgrindの利用
valgrindを繰り返し使ってさらに証拠を集める
証拠を調べる
修正の確認
Cツールボックス
7章 高度な関数
理想的な相手を探す……
関数にコードを渡す
find()に関数の名前を伝える必要がある
関数名はすべて関数へのポインタである……
でも、functionデータ型はない
関数ポインタの作成方法
C標準ライブラリでソートする
関数ポインタを使って順序を設定する
返信の自動化
関数ポインタの配列を作成する
関数に伸縮性を持たせる
Cツールボックス
8章 スタティックライブラリとダイナミックライブラリ
銀行に持っていけるコード
山かっこは標準ヘッダに使う
でも、コードを共有したい場合はどうなるの?
.hヘッダファイルの共有
フルパス名を使って.oファイルを共有する
アーカイブには.oファイルがある
arコマンドでアーカイブを作成する……
最後に、他のプログラムをコンパイルする
ヘッドファーストジムがグローバルに展開中
カロリーの計算
でも、状況はもう少し複雑……
プログラムは多くの部品から作られる……
ダイナミックリンクは実行時に起こる
.aを実行時にリンクできる?
まず、オブジェクトファイルを作成する
ダイナミックライブラリの呼び名はプラットフォームによって異なる
Cツールボックス
Cラボ2 OpenCV
9章 プロセスとシステムサービス
システムコールはOSへのホットライン
誰かがシステムに侵入した……
問題はセキュリティだけではない
exec() 関数を使えば、より詳細に制御できる
exec() 関数がたくさん
配列関数:execv()、execvp()、execve()
環境変数を渡す
ほとんどのシステムサービスは失敗したときに同じように動作する
RSSでニュースを読む
exec()はプログラムの終点
fork()とexec()で子プロセスを起動する
Cツールボックス
10章 プロセス間通信
入力と出力のリダイレクト
典型的なプロセスの中を調べる
リダイレクションはデータストリームを置き換えるだけ
fileno()はディスクリプタを教えてくれる
待たなければいけないこともある……
子プロセスとの連絡を保つ
パイプでプロセスをつなげる
事例研究:ブラウザで記事を開く
子プロセスでは
親プロセスでは
ブラウザでWebページを開く
プロセスの死
シグナルを捕捉して独自のコードを実行する
sigactionはsigaction()で登録する
シグナルハンドラを使うようにコードを書き換える
killを使ってシグナルを送る
コードにモーニングコールを送る
Cツールボックス
11章 ソケットとネットワーキング
インターネットノックノックサーバ
ノックノックサーバの概要
BLAB:サーバがインターネットとやり取りする方法
ソケットは標準的なデータストリームではない
サーバが適切に開始しないことがある
なぜ常にエラーを調べるように言われるの?
クライアントからの読み込み
サーバは同時に1人しかやり取りできない
クライアントごとにプロセスをfork()できる
Webクライアントの記述
クライアントの担当
IPアドレスのソケットを作成する
getaddrinfo()はホストのアドレスを取得する
Cツールボックス
12章 スレッド
タスクは逐次的?
……プロセスでは必ずしも解決にはならない
単純なプロセスは一度に1つのことを行う
追加スタッフを雇う:スレッドの使用
どのようにスレッドを作成するの?
pthread_createでスレッドを作成する
このコードはスレッドセーフではない
信号機を追加する
ミューテックスを信号機として使う
Cツールボックス
Cラボ3 Blasteroids ゲーム
付録i 未収録事項
1.演算子
2.プリプロセッサディレクティブ
3.staticキーワード
4.データの大きさ
5.自動テスト
6.gccの詳細
7.makeの詳細
8.開発ツール
9.GUIの作成
10.参考文献