C を理解すればより優れた高レベル プログラマになれるという具体的な例は何ですか?

StackOverflow https://stackoverflow.com/questions/2077913

  •  21-09-2019
  •  | 
  •  

質問

といった疑問の存在は知っています。 これです そして これです. 。説明しましょう。

ジョエルの記事を読んだ後 基本に立ち返って そして、SO で多くの同様の質問を見て、C のようなものを知っていればより優れた高レベル プログラマになれる具体的な例は何だろうと考え始めました。

私が知りたいのは、このような例がたくさんあるかどうかです。多くの場合、この質問に対する答えは次のようなものです。C を理解すると、内部で何が起こっているかをよりよく理解できるようになります" または "プログラムには強固な基盤が必要です」と、これらの回答にはあまり意味がありません。低レベルの概念を知ることでどのようなメリットが得られるのかを理解したいのですが、

ジョエルはいくつかの例を挙げました。バイナリ データベースと XML、および文字列。しかし、2 つの例は、C やアセンブリを学習することを正当化するものではありません。そこで私の質問は次のとおりです。 C を理解すればより優れた高レベル プログラマになれるという具体的な例は何ですか?

役に立ちましたか?

解決

学生を教えるだけハイレベル言語を学ん人での作業との私の経験は、彼らが抽象化の一定の高いレベルで考える傾向があり、そして彼らは「すべては自由のために来る」ことを前提としていることです。彼らは非常に有能なプログラマーになることができますが、最終的に彼らは、パフォーマンスの問題があり、それはそれらを噛まないように来ていくつかのコードに対処する必要があります。

あなたがCで多くの作業するときは、メモリの割り当てについて考えます。 (それが問題だ場合、キャッシュの局所性)あなたは、多くの場合、メモリレイアウトを考えます。あなたは、特定のグラフィックス操作だけで多くの費用方法と理由を理解します。どのように効率的または非効率的な特定のソケットの振る舞いです。どのようにバッファが働くなど、私はあなたがそれをカバーの下に実装されているのか分からないときのパフォーマンスを考えると、より高いレベルの言語で抽象化を使用すると、時にはあなたに「は、余分な秘密のソース」を与えると感じています。

たとえば、Javaは、ガベージコレクタを持って、あなたは直接メモリに直接物事を割り当てることはできません。そして、まだ、あなたは、これはCで問題になるので、同じ理由のパフォーマンスに影響を与える(カスタムデータ構造を持つなど、)特定の設計上の選択を行うことができます。

また、より一般的に、私はそれが(ほとんどの学校が教える)ビッグO記法を知っているが、それは現実のアプリケーションで定数も重要である(これは学校がしようとしていないだけに、パワープログラマのために重要であることを感じて無視する)。私の事例の経験は、おそらくので、私は上記のものの、両方の言語レベルのスキルを持つ人々は、一定の理解を持っている傾向があることです。

また、私は低レベルライブラリとインフラとのインターフェースを見ている多くのより高いレベルのシステム。例えば、いくつかの通信、データベースやグラフィックスライブラリ。いくつかの特定のデバイスなどのドライバあなたは、パワープログラマであれば、あなたはeventiallyそこにベンチャーする必要があり、それは、少なくとも何が起こっているかのアイデアを持っているのに役立ちます。

他のヒント

低レベルのものを知ることは大いに役立つことができます。

レーシングドライバーになるために、あなたはどのようにタイヤのグリップの基本的な物理学の道を学び、理解する必要があります。誰もが非常に高速運転することを学ぶことができますが、あなたをできるようになります、性能のものと最後の数パーセントを取得するには、「低レベル」のもの(力と摩擦、レーシングライン、細かいスロットルとブレーキ制御など)をよく理解する必要がありますレースに勝つます。

あなたはCPUアーキテクチャがコンピュータにどのように機能するかを理解していれば、

たとえば、あなたがそれをよりよく動作するコードを書くことができます(たとえば、あなたが特定のCPUのキャッシュサイズや各CPUのキャッシュライン内のバイトの特定の番号を持って知っている場合、あなたのデータ構造と、キャッシュを最大限に活用するためにそれらにアクセスする方法を手配することができます - 例えば、順に配列の多くの要素を処理すること)により、CPUのキャッシュに、多くの場合、より高速なランダム要素を処理するよりもです。あなたは、マルチコアコンピュータを持っている場合は、作業をスレッドのような低レベルの技術ができます(同じようにスレッドに災害につながることができ、低レベルを理解していない)、巨大な利益を与えた方法を理解する。

あなたは一つのファイルから読み込まれ、他に書き込む場合は、

あなたはどのようにディスクI / Oとキャッシュ作品を理解していれば、あなたはそれでうまく動作するようにファイル操作を変更することができる(例えば、RAMにデータの大規模なバッチで作業はIを軽減することができます/ Oあなたのコードの読み取りと書き込みのフェーズ間の競合、および大幅に改善し、スループット)

あなたは仮想関数がどのように動作するかを理解していれば、

、あなたもの仮想関数がを使用して、高レベルのコードを設計することができます。間違って使用した場合、彼らは深刻なパフォーマンスを妨げることができます。

あなたは、描画の処理方法を理解していれば、

は、描画速度を向上させるために巧妙なトリックを使用することができます。例えばあなたは交互に64白と黒の四角を描画してチェス盤を描くことができます。しかし、それは(あなたが唯一の描画色倍の代わりに、64時間を変更する必要があるため)32白いsqares、その後32黒いものを描くことが多い高速です。しかし、あなたが実際に白で、その後、ボード全体が黒XOR軒並み4本のストライプとボードダウン4本のストライプを描くことができ、これは非常に速く、まだ(2色の変化、そして唯一の9の長方形ではなく、64の描画する)ことができます。水平思考:これはチェス盤のトリックはあなたに非常に重要なプログラミングのスキルを教えています。あなたのアルゴリズム井戸を設計することにより、あなたは多くの場合、あなたのプログラムがどのように動作するかを十分に大きな違いを生むことができます。

C、またはそのことについては、任意の低レベルのプログラミング言語を理解して、あなたのメモリ使用量のようなものを理解する機会を与え、ポインタ/オブジェクト参照がどのように動作するか、(つまり、なぜ数百万重いものを作成するために悪いことです)など。

問題は、私たちが今まで抽象化のレベルを高める作成してきたように、私たち自身が、レゴが実際にどのように機能するかを理解することなく、「レゴブロック」プログラミングをたくさんやって見つけることです。そして、ほとんど無限のリソースを持っていることによって、私たちは水のようにメモリやリソースを治療開始し、状況をより多くの鉄を投げることによって問題を解決する傾向があります。

Cに限定されるものではないが、

、Arduinoのか、古い学校の8ビット・プロセッサのようなはるかに小さく、メモリに制約のシステムと低レベルでの作業に多大な利点があります。それはあなたがはるかに親しみ、パッケージ内の金属コーディングに近い体験、および512Kに時間のアプリを絞るを過ごした後、あなたは一日プログラミングにあなたの日内のより大きなレベルでこれらのスキルを適用する自分自身を見つけるだろうことができます。

言語自体が重要な、しかし、すべてのビットが一緒に来て、どのように近いハードウェアのレベルで効率的に作業する方法についてより深い理解を持っていないので、

は、任意のソフトウェア開発者に有益なスキルのセットです。

が1の場合は、Cを知ることは、あなたがメモリをOSにし、他の高レベルの言語でどのように機能するかを理解するのに役立ちます。メモリ使用量であなたのC#やJavaプログラムの風船場合は、(基本的には単なるポインタで)参照は(あなたがCで独自のものを作るから取得した)あまりにもメモリを取り、どのようなデータ構造が実装されているの多くを理解していることを理解し、あなたがいることを理解するのに役立ちますあなたの辞書が実際に使用されていないメモリを大量に確保されます。

他の場合は、Cを知ることは、あなたがより低いレベルのオペレーティング・システムの機能を利用する方法を理解するのに役立つことができます。あなたは、多くの場合、これは必要ありませんが、時にはあなたは、メモリマップドファイルを、またはC#でマーシャリングを使用する必要があり、そしてCが大幅にそれが起こるとき、あなたがやっているかを理解するのに役立ちます。

私はCは、ネットワーク・プロトコルの私の理解を助けていると思いますが、私は具体的な例で私の指を置くことはできません。私は別のものを読んでいたSO誰かがCのビットフィールドは、「基本的に役に立たない」であり、私はCビットのフィールドは、低レベルのネットワークプロトコルを表す方法をエレガントに考えていたかについて文句を言った、他の日を疑問視。ビットの構造を扱うハイレベルの言語は常に混乱を終わります!

一般的には、より多くのあなたが知っているが、より良いプログラマはあなたがなります。

(などのPython、またはPHPなど)は、より高いレベルの言語では真ではないという仮定があるかもしれませんので、

しかし、時にはCのような別の言語を、知ることは、あなたが間違ったことを行うことができます。例えば、一つのリストの長さを見つけることNはリストの長さであり、O(N)であるかもしれないと仮定かもしれません。しかし、これはおそらく、多くのハイレベル言語のインスタンスではそうではありません。 Pythonでは、ほとんどのリストのようなもののためのコストはO(1)です。

役立つ言語の仕様についての詳細を知ることが、間違った仮定を行うために1つを導く可能性がある、より一般的には知っています。

ただ、Cは、あなたがより良いことはないだろう "知っている"。

しかし、あなたは全体のことを理解していれば、どのようにネイティブバイナリ仕事、アーキテクチャ上の制限が何であるか、それを持つCPUの仕事を、どうするか、あなたはCPUのために簡単なコードを書くことができます。

例えば、L1 / L2キャッシュはあなたの仕事にどのような影響を与えるか、そしてどのようにL1 / L2キャッシュでより多くのヒットを持っているあなたのコードを書く必要があります。 C / C ++での作業や重い最適化を行うときは、物事のようなものにまで行く必要があります。

それはCが他の多くの言語よりも、ベアメタルに近いということであるように、

これはそんなにCを知られていません。あなたはそれを自分で行う必要があるので、/割り当て解除メモリを割り当てる方法をより認識する必要があります。それを自分で行うことは、あなたが作る多くの決定の影響を理解するのに役立ちます。

私に任意の言語を限り、あなたは、コンパイラ/インタプリタは(基本的に)マシンにあなたのコードをマップする方法を理解として許容可能です。それは、これを直接公開した言語で行うのは少し簡単ですが、あなたは、読書のビットは、メモリが割り当てられ、編成されている方法を見つけ出すことができるはず、構築物が何であるか、他のものより最適なインデックスパターンの種類をしています特定のアプリケーションのためのより効率的な、など。

さらに重要なことは、私が思うに、オペレーティングシステム、メモリ・アーキテクチャ、およびアルゴリズムの十分な理解です。あなたのアルゴリズムがどのように機能するかを理解していれば、なぜ(リスト対例えば、HashSetの)別の上の1つのアルゴリズムやデータ構造を選択する方が良いだろう、とあなたのコードは、マシン上にマッピングする方法、あなたが使用している言語の問題ではないはずます。

これは、私がどのようにプログラミングを学び独学したか、特に C を理解する方法についての私の経験です。これは 1990 年代初頭に遡るため、少し古いかもしれませんが、情熱と意欲は重要です。

  • EGA/VGA プログラミングなど、コンピューターの低レベルの原理を理解する方法を学びます。 リンク PC への C プログラマーズ ガイドの Simtel アーカイブにアクセスしてください。
  • TSR の仕組みを理解する
  • のアーカイブ全体をダウンロードする ボブ・スタウトの抜粋 これは C コードの大きなコレクションであり、ただ 1 つのことだけを実行します。コードを研究して理解するだけでなく、スニペットのコレクションは移植性を追求しています。
  • 国際難読化 C コード コンテストで閲覧する (IOCCC) オンラインで、C コードがどのように悪用されるかを確認し、言語の複雑さを理解してください。最悪のコード悪用が勝者です。アーカイブをダウンロードして調べてください。
  • 私と同じように、悪名高い Ponzo の C チュートリアルが大好きで、非常に役に立ちました。残念ながら、アーカイブを見つけるのは非常に困難です。どこで入手できるか知っている人がいたら、コメントを残してください。この回答を修正してリンクを含めます。私が覚えているもう 1 つのチュートリアルは、Coronado の [Generic?] C チュートリアルですが、これも私の記憶があやふやです...
  • 博士を見てください。Dobb の日記と C ユーザーの日記 ここ - 今でも印刷物として入手できるかどうかはわかりませんが、古典的なものでした。印刷物を手に持ち、家に引き裂いて何が起こるかを確認するためにコードを入力したときの感覚を覚えています。
  • ~の古代のコピーを手に入れる ターボC v2 これは borland.com から入手でき、16 ビット C プログラミングで遊んで感触を掴み、ポインタをいじってみるとよいと思います。確かに古いものですが、ポインタを使って遊ぶのは問題ありません。
  • 理解して学ぶ ポインタ、リンク ここ 遺産へ Simtel.net - C の達人になるための重要なリンクです。これ以上良い言葉はありませんが、C プログラミング言語に関するダウンロードも多数あります。実際に Simtel CD Archive を注文して C のものを探したのを覚えています...

あなたは抽象的なあなたから離れて、他の言語は、明示的なメモリ管理(malloc)を含めるとポインタを直接扱うことをCに直接対処する必要が物事のカップルます。

私のガールフレンドは、コンピュータサイエンスの学位を取得して(彼らは主にJavaの、スキーム、とPythonを使用する)MITを卒業から1つの学期で、彼女は現在、そのコードベースC ++にある会社で働いています。最初の数日間は、彼女はすべてのポインタ/参照/などを理解することは難しい時間を過ごしています。

私はパスの参照値による参照渡し対について混乱はなかったので、

一方で、私は、非常に簡単にJavaへのC ++から移動います。

同様に、C / C ++では、すべてが独自の別個の特性を持つオブジェクトであるPythonやRubyのような言語とは対照的に、プリミティブは、異なる方法でビットの同じセットを処理するだけコンパイラであることが一層明らかです。

上記のアドバイスの一部を説明するための簡単な (完全に現実的ではない) 例。一見無害に見えるものについて考えてみましょう

while(true)
   for(Iterator iter = foo.iterator(); iter.hasNext();)
       bar.doSomething( iter.next() )

あるいはさらに高いレベル

while(true)
    for(Baz b: foo)
        bar.doSomething(b)

ここで考えられる問題は、ラウンドするたびに、 その間 ループでは、新しいオブジェクト (イテレータ) が作成されます。プログラマの利便性だけを重視するのであれば、後者の方が断然優れています。しかし、ループを効率的にする必要がある場合、またはマシンのリソースに制約がある場合は、高級言語の設計者のなすがままになります。

たとえば、高パフォーマンスの Java を実行する場合の典型的な問題は、ガベージ (割り当てられたすべての Iterator オブジェクトなど) が再利用される間に実行が停止することです。ソフトウェアが、飛来するミサイルの追跡、旅客機の自動操縦、または GUI が応答しなくなった理由をユーザーに疑問に思わせないようにする機能を備えている場合は、あまり良いとは言えません。

考えられる解決策の 1 つは (高水準言語での)、イテレータの利便性を次のように弱めることです。

Iterator iter = new Iterator();
while(true)
    for(foo.initAlreadyAllocatedIterator(iter); iter.hasNext();)
       bar.doSomething(iter.next())

ただし、これはメモリ割り当てについてある程度の知識がある場合にのみ意味をなします。そうでない場合は、単なる厄介な API のように見えます。利便性には常にコストがかかりますが、低レベルのものを知ることは、それらのコストを特定して軽減するのに役立ちます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top