web-dev-qa-db-ja.com

Cプログラマは何を知っておくべきですか?

すべてのまともなCプログラマーが知っておくべき/知っておくべき概念/技法/言語機能は何ですか?私が知りたいのは、私のC知識のいくつかの可能なギャップを埋めることができるようにするためです。

12
Anto

Cに固有ですか?ほとんどの手続き型言語に共通する標準の構成要素は別として、私は言わなければならないでしょう:

  • (ab)プリプロセッサを使用する
  • リンカーとコンパイラ
  • ポインターポインターポインター!
  • 配列はどのようにポインタであるか
  • C文字列のしくみ、およびそれらがポインタと配列になる方法
  • 悪いC文字列の使用がバッファオーバーフローを引き起こす可能性
  • 何かを何かにキャストする方法(結局のところすべて1と0だけです:))
  • 手動メモリ管理malloc/free
  • スタックとヒープ
  • ポインターのエイリアシング(C99ではなぜ無効か)
  • 厳密にクラスではなく、公開された一連の関数を使用したモジュール(.h/.cファイル)の観点から開発について考える
  • 組合
  • Sprintfが足を吹き飛ばせる理由
  • 関数ポインタ
19
Doug T.

ポインタを理解すれば、コンピュータを理解できます。

8
PP.

ピタグラの優れた答えに加えて、

char (*(*funcs[4])())[10]などの複雑な宣言を書き込む(または少なくとも読み取る)方法

funcsは、charのarray [10]へのポインターを返す関数へのポインターのarray [4]です

5
tcrosley
  1. 整数昇格規則
  2. すべてを既知の値に初期化する
  3. GOTOは、例外/障害を処理するために使用される場合は特に悪ではありません
  4. mallocおよび/またはcallocはNULLを返すことができます...チェックの戻り値を確認してください
  5. 小さなメモリ割り当てが頻繁に発生すると、ヒープが断片化する可能性があります。
  6. ポインター演算
  7. ビットマスクはあなたの友達です
  8. x >> 1は、符号なし整数のx/2と同等です
3
Pemdas

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を安全かつ効果的に使用するには、実際にそれらの低レベルの詳細を理解する必要があります。

2
Aidan Cully

Cプログラマは知っておくべき...他の言語! ;-) OOP、関数型プログラミングなど、さまざまなパラダイムの他の言語の概念を知ることは常に実りがあります。

もっと真剣に、難読化されたプログラミングコンテストを見るのは楽しいし、奇妙なことに、良い経験にもなります。

2
PhiLho

他の良い答えに加えて、リストに 防御的プログラミング テクニックを追加したいと思います。

例えば。関数の開始/終了時にアサートを使用して契約を確認します。

0
AndersK