すべてのまともなCプログラマーが知っておくべき/知っておくべき概念/技法/言語機能は何ですか?私が知りたいのは、私のC知識のいくつかの可能なギャップを埋めることができるようにするためです。
Cに固有ですか?ほとんどの手続き型言語に共通する標準の構成要素は別として、私は言わなければならないでしょう:
ポインタを理解すれば、コンピュータを理解できます。
ピタグラの優れた答えに加えて、
char (*(*funcs[4])())[10]
などの複雑な宣言を書き込む(または少なくとも読み取る)方法
funcsは、charのarray [10]へのポインターを返す関数へのポインターのarray [4]です
Pythagrasの回答へのコメントで「バッファオーバーフロー」について述べましたが、私が少し意味したことをおそらく明確にする必要があります。 Cでは、thatメモリを直接操作するのは危険であることを知るだけでは十分ではありません。危険であることの正確な方法も理解する必要があります。私はこれらのすべてのケースで「足で自分を撃つ」という比喩は本当に好きではありません-多くの場合、それはあなた引き金を引くことではありませんが、多くの場合、反対の興味を持つ俳優ですあなたと/またはあなたのユーザーの。
たとえば、降順スタックを備えたアーキテクチャ(ほとんどの一般的なアーキテクチャはこの法案に当てはまる-x86およびARM一般に含まれています)で、関数を呼び出すと、関数の戻りアドレスは次の場所に配置されますスタックafter関数の本体で定義されたローカル変数したがって、バッファをローカル変数として宣言し、その変数を次のようにバッファオーバーフローをチェックせずに外部に公開するとします。
_void myFn(void) {
char buf[256];
gets(buf);
}
_
外部ユーザーはスタックからの戻りアドレスを上書きする文字列をあなたに送ることができます-基本的に、彼は現在の関数につながるコールグラフのあなたのプログラムのランタイムの考えを変えることができます。したがって、ユーザーは、アーキテクチャの実行可能コードのバイナリ表現である文字列、myFn
からスタックをオーバーフローするのに十分なパディング、およびmyFn
の戻りアドレスを上書きするための追加データを提供します彼があなたに与えたコードを指し示します。これが発生した場合、myFn
が通常は呼び出し元に制御を返したときに、悪意のあるユーザーが提供したコードに分岐します。信頼できないユーザーに公開される可能性のあるC(またはC++)コードを記述する場合、この攻撃ベクトルを理解する必要があります。スタックに対するバッファオーバーフローがヒープに対するものよりも(常にではないが)多くの場合より容易に悪用される理由を理解する必要があり、ヒープ内のメモリがどのように配置されるかを理解する必要があります(あまり詳細ではありませんが、必ずしもmalloc()
'ed領域に制御構造が含まれているという考えは、プログラムが別のmalloc()
またはfree()
でクラッシュする理由を理解するのに役立ちます。
Cはマシンの動作に関する低レベルの詳細を公開し、今日広く使用されている他のユーザー編集言語よりもマシンを直接制御できます。大きな力には大きな責任が伴います。Cを安全かつ効果的に使用するには、実際にそれらの低レベルの詳細を理解する必要があります。
Cプログラマは知っておくべき...他の言語! ;-) OOP、関数型プログラミングなど、さまざまなパラダイムの他の言語の概念を知ることは常に実りがあります。
もっと真剣に、難読化されたプログラミングコンテストを見るのは楽しいし、奇妙なことに、良い経験にもなります。
他の良い答えに加えて、リストに 防御的プログラミング テクニックを追加したいと思います。
例えば。関数の開始/終了時にアサートを使用して契約を確認します。