まえがき:最近、ある人が文句を言っていました。私は彼の意見には賛成しませんが、少なくとも彼は、「親指ほどの大きさのコンピューターで」プログラミングをしたり、ある言語のブートストラップを書いたりするのであれば、さりげなくC.私に言わせれば、デバイス・ドライバを書くとか、プラットフォーム固有のカーネルを書くとか、とにかくCを使えばいいのです。
今はウェブ開発者ですが、夜だけです。昼間は組み込みマイクロプロセッサのファームウェアを書いているので、C言語は今でも私の選択言語です。私が言っているマイクロプロセッサとは、トースターなどに組み込まれているもので、コードスペースが64KB程度、RAMが2KB程度しかないので、使える言語は基本的にアセンブリとCだけです。
そして次第に、C言語を使えば使うほど、C言語が煩わしいものでなくなっていくことに気づきました。そこで、世界で最もよく使われているシステムレベルのプログラミング言語への賛辞を書こうと思いました。
1.ケーアンドアール
序文さえも非常に素晴らしい。C言語は巨大な言語ではないので、重い本で解釈すべきではありません。K&Rの簡潔さとポイント・バイ・ポイントのアプローチは、C言語の成功に不可欠かもしれません。
同じようなプログラミングの教科書で、レオ・ブロディの『ThinkingForth』もお気に入りです。もちろん、340万行のコード、私がまだ読んでいないだけで、他にも本当に良い本があるはずです。
2.非常に簡潔
C言語が簡潔な言語であることは、本当に利点です。C言語を学ぶのに必要なのは、型を理解し、フロー制御に慣れ、ポインターを扱えるようになることだけです。あとは関数だけです。K&Rがこの低レベルの命令型言語を利用し、わずか11行で実装しているという事実は、C言語の簡潔さを強く証明するものです。
3. IOCCC
私が本当に多くのことを学んだのは、Fabrice Bellardによる「難読化された小型Cコンパイラ」であるOTCCでした。コンパイラの設計について多くのことを学びました。主に、Cコンパイラは340万行の巨大なコードである必要はないということです。また、『コンパイラを作ろう』から学んだことも生かし、CからForthへのコンパイラを書くことにしました。
4.変数が定義され、同様の形式で使用されます。
これは、非常に複雑なものの定義方法を覚えておくのに便利です。たとえば、10個の図形を含む配列へのポインタは、orにすべきでしょうか?演算子の方が優先順位が高いことを覚えておけば、括弧が必要なことが理解できます。
5.非常に小さいサイズで "hello, world "をコンパイルします。
これは特に組み込みプログラミングに最適で、C言語には巨大なランタイムがありませんし、多くの組み込みプロセッサでは、何もしないプログラムは3、4バイトにしかコンパイルされません。完全な "hello, world "プログラムは、Windows XPでさえ、1.5KBにしかコンパイルされません。
Pythonのような他の言語が現時点でCに追いつき、あるいはCの一部になることができれば、組み込みの世界でさらに目立つ存在になると思います。
#p#
6.グローバル変数はデフォルトで外部変数
グローバル変数を使うのは良くない習慣だ!」と言うでしょう。.しかし、組み込みシステムでは違います。例えば、あるファイルにグローバル変数があり、別のファイルにもグローバル変数があるとします。たまたま'static'を付け忘れた場合、それらは同じ変数であり、あなたはそれに気づかず、警告もヒントもありません.
特にキーワードが手元にある場合、この動作は非常に奇妙に思えます。しかし、2つの異なる意味に慣れていれば、簡単に避けることができます。しかし、それでも非常に厄介です。
7.2つの異なる意味
なぜ関数本体内と関数本体外では全く異なる2つの意味があるのか、どなたか説明できますか?関数本体内では、"static"、つまり「関数呼び出しの間、この変数を一意に保つ」という意味です。しかし、関数本体の外では、「この変数はこのファイルに対してプライベートである」という全く異なる意味になります。なぜ後者の場合はorを使わないのですか?
8.以下の優先順位==。
組み込みプログラミングでは、このような文は常に好んで使われます。しかし、「&」の方が「==」よりも優先順位が高いような気がして、括弧のペアを書き忘れてしまうことがよくあります。しかし、そうではないので、余分な括弧のペアを使用する必要があります。
しかし、この状況には歴史的な理由があります。CはBから生まれたもので、Bには&しかなく、&&演算子はありませんでした。Ritchieが&&演算子を導入したとき、彼らは元のB側のコードを動作させたかったので、&&の優先順位を==よりも低くしました。
9.マクロはそれほど強力ではありません
再帰的なものは素晴らしいアイデアですが、気の遠くなるようなメソッドに頼らずに前処理ループを簡単に行うにはどうすればいいのでしょうか?同様に、私がよく遭遇する状況がいくつかあります。例えば、一度に1つの変数だけを変更する必要がありながら、intと文字列の両方の形式でバージョン番号をプログラムに与えるにはどうすればよいでしょうか?
#define VERSION_INT 209
#define VERSION_STR "2.09"
上記のコードでは、バージョン番号を更新するときに必ず2カ所を変更する必要があります。そして、特別な合計はあまり役に立ちません。私が見つけた唯一の解決策は、実行時の修正を伴うものでした。
10.リフレクションに対応していません。
マクロシステムがもう少し強力であれば、リフレクション機構は必要なかったでしょう。もしかしたら悪用するかもしれません。私が本当に言いたいのは、C言語ではコードを生成するようなコードは書けないということです。
なぜプリプロセッサをC言語で書かないのですか?そうすれば、ループのアンロールや、より強力なマクロ機構、さらにIOCCCの奇妙なアイデアなど、無限の可能性が生まれるでしょう。:-)
Cの父親がCの欠点を素直に認めることができたのは、とても貴重なことだと思います。デニス・リッチーが言ったようにね:
"Cは奇妙な振る舞いをし、欠点だらけですが、大成功です"
これについては、彼の論文 『The Development of the C language 』を読んでください。
総合的に判断して、C・ドレガー。





