本書「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は、こんな感じ。
- いきなりCで書くな -- それは今日日「早すぎる最適化」
- 書くなら手を抜くな -- 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.参考文献
|
このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。