『新・明解C言語 入門編』の感想

はいどーも人生の入門者です。
本日は『新・明解C言語 入門編』の感想記事を書こうと思いますよ。
ちなみになんで今更C言語かというと、C++を学ぶための前勉強的な感じです。
色んな記事でC++のサンプルコードが載っているので、それを読めるようになりたいなーというのと、C++で仕事増えたらなーって感じですね。

コードを真似しすぎは注意

最初に書いておくと、素人目にも「いやー、この書き方はないでしょ」と思うようなコードがサンプルとして挙げられています。
そこは注意が必要かなーと思いました。
初心者がこれを真似しちゃうと、いわゆるクソコードの再生産となりそうです。
ただ入門書なのでそこら辺は仕方ないかなーとも思います。
が、「なるべくreturn文を一つに」とかいう、端的に言ってクソコード量産を推奨することも書かれているので、著者さん自体があまりコードの綺麗さにこだわっていないのかなーとも思いました。
何にせよ解説はともかくコード自体は鵜呑みにはしないほうがよいです。

また、もっと平易に書けるはずのコードを、わざとトリッキーに書いて「難しい例」として挙げています。
難しく書く必然性は全くないのに、「こちらの方がカッコイイのか」と思って真似する人がいたら地獄だろうなーとは思いました。
例えば

ですけど、普通に

と二行に分けたほうが何をやっているのかが自明です。
このあとの例で出てくるfor文を純粋な繰り返し以外の用途で使ってるのも「ウーン……」って感じですかね。
WHATじゃなくてHOWに傾きすぎかなーと思います。

アルゴリズムはカッコイイ

と最初に色々書きましたが、入門書としてはわかりやすい方かなーと思いました。
また、僕は数学できないマンなので、色々と参考になるアルゴリズム(と言うほどのものかどうかは謎ですが)がありました。
例えば「x % 10で一番下の桁の数字がわかる」というものは目からウロコでした。
一番下の桁の数字を取得しなければならないプログラムを実際に作成したことはありませんが、恐らくこれを知らなければ僕は「まずtoStringで文字列に変換」「末尾を取得」「それから数字に戻す」という手順を踏んでいたでしょう。
これはほとんどの環境でx % 10より遅い処理となるはずで、無駄もいいところですね。
なお、これの2進数バージョンや16進数バージョンの理屈も説明されていました。

あとは「番兵」という考え方も面白かったです(詳しい説明は省きますが、ある値を線形探索するするときに使えるものです)。
ただコチラは自分で検索用のアルゴリズムを作らない限りは使うことはまあないかなーと思いました。
実際コレクションを操作するならfindやらFirstOrDefaultやらを使うんじゃないかなーと思います。

関数の中でstatic

C言語では関数の中でstaticをつけて変数を宣言することができるようです。
効果としてはJavaScriptのクロージャに近いかなと思いました。
オブジェクト指向でプログラムを組むなら大して必要ない機能な気はしましたが、C言語では便利そうですね。

頻繁に出てくる「処理系によって異なる」

どうもC言語で作成したプログラムは「処理系によって異なる」結果になることが往々にしてあるようです。
本書でも頻繁に「処理系によって異なる」という注釈が使われています。
この「処理系によって異なる」結果になるものに依存してプログラムを組むと、予期しないエラーが発生するのだろうなーと思いました。
わりと罠ですね。

ポインタ

これですこれ。
僕が一番知りたかったもとい勉強したかったのはポインタについてです。
ポインタは躓く方が多いらしく、本書でもそれなりにページが割かれています。
とはいえあくまでも本書は入門書なので、そんなに難しい部分はなかったかなーと思いました。
配列とポインタの関係性については「ホー」と思いましたが、これは言語によっては全然違う作りをしているのではないかなーと思いました(どの言語か忘れましたが、配列はメモリ上に連続しておかれていない、みたいな説明があったのもありましたので)。

しかしポインタ、やっぱり「めんどくせぇな」という印象が強いです。
バグをガシゴシ埋め込みそうで嫌ですね。
使わずに済むならそれが一番な気がするんですが、C++でも使わないとキツイんですかねー。

唐突に解説なしで使われる

本書に限ったことではないのですが、入門書なのに知らない文法が唐突に出てくることあるんですよね。
これは単に著者が意識せずに書いただけなんでしょうが、ちょっと困ります。
例えば文字列のコピーとして以下のようなコードが掲載されていました。

一見したところ何の変哲もない関数ですが、ここまでの説明で「*str_copy」これの解説がありませんでした。
ググったところ、関数名の前に間接演算子を置くとポインタを返す関数ができるようです。

あと*tが宣言されていますが、以下のコードじゃダメなの? という疑問がありました。

これについては少ししか触れられていなかったので、*tが存在する意義がいまいち判然としませんでした。
というわけでググったところ、以下の質問がヒットしました。
https://teratail.com/questions/15715
非常にわかりやすい説明です。
実際に*tなしで関数から戻り値を得るとおかしなことになるのがわかりました。
いやあ助かりました。

文字列の扱いがドチャクソめんどくさい

JavaScriptやC#ではかなり直感的に文字列を扱うことが可能です。
ですがC言語は直感的とは程遠い方法でしか文字列を扱えないため、ひじょーにめんどくさい、もといバグまみれになりそうだという印象でした。
ただC言語を学んだおかげで、C#でなぜ文字列がイミュータブルなのかちょっぴりわかりましたよ。
あとC++ちょっと見た感じ、こっちはstring型が普通にあるようですね。

知りたかったことが意外と載ってない

用語はちょくちょく聞くけれど、内容は詳しく知らない、みたいなものの解説も期待していたのですが、触れられていないものも多くてそこはガッカリでした。
例えば以下のものでしょうか。

・関数ポインタ
・共用体型
・メモリ関連の操作(mallocとか)

特にメモリ関連の操作は詳しく知りたかったので(そこがキモだと思ったので)、これは手痛いですね。

ただ逆に「あんまり知らなかったけど詳しく知れた」ものも当然あります。
例えばテキストファイルとバイナリファイルの違いでしょうか。
あんまり意識せずに使っていたのですが(ぶっちゃけJSONで書くことが多かったので)、バイナリファイルもなるほどなぁという感じです。
シリアライザなんかで使われるのかなーと思いました(よく調べてないので単なる想像ですが)。

終わりに

「C++の前に少しはC言語についても知っておいた方がいいだろう」という考えのもと、C言語の入門書として本書を選びました。
まあ内容の半分以上は「知ってるよそれくらい」というものでしたが、もう半分は「C言語だとそうなるのか!」という発見があったので、やっぱりC++の前に読んでおいてよかったなあとは思いました。

ほなそんな感じでまた。
お仕事も募集中ですよ。

フォローする