高レベルのOOP言語(C#やJavaなど))をかなり長い間使用してきました。4人のギャングのようなパターンを知っていて、コードを適切に読み書きでき、考慮されています仲間の先輩。
低レベルのC開発に移行しています。私の経歴の結果として、私は低レベルの開発/実装に固有のテクノロジーやスキルの多くに慣れていません。
より高いレベルから来たときにC開発で成功するために理解する必要がある技術と開発アプローチの主な違いは何ですかOOPバックグラウンド?
それはあなたが得る必要があるだろう「金属にどれだけ近いか」に依存します。しかし、慣れていないかもしれないいくつかの一般的な事項:
すぐに、あなたが多くの注意を払わなければならない最初のことは、リソース管理です。 Cはガベージコレクターを実行せず、自動ファイナライザー(別名デストラクタ)もないため、メモリのチャンクを割り当てるか、ファイル/ソケットを開くことは、そのリソースのライフタイムを手動で追跡して解放する必要があることを意味しますプログラムのいくつかのポイント。これは、おそらくJava/C#からのパラダイムにおける最大のシフトですが、慣れてきたら大した問題ではありません。現在、リソースリークの追跡に役立つ非常に優れたツールが用意されているため、恐れることなく生活する必要はありません。
Cはセーフティネットを提供していません。つまり、配列の境界チェック、メモリの保護、および一般的なプログラミングのミスに対する実行時の保護はほとんどありません。 「Cは大きな銃ですが、それで足を撃つことは非常に簡単です」と聞いたことがあるかもしれません。それは事実です。高い実行パフォーマンスにはいくつかのトレードオフが必要であり、ランタイムチェックを振ることもその1つです。プログラムが必要とする可能性のある安全メカニズムはすべてユーザーが実装します。この言語には、すぐに使えるものはほとんどありません。
Cは非常に軽量であり、その標準ライブラリも同様です。標準Libは基本的に、少数のIO関数と数学関数で構成されています。それについてです。組み込みCを使用している場合は、それさえ得られない可能性があります!ニースのコンテナーや汎用アルゴリズムはありません。繰り返しますが、言語の精神で、アプリケーションが機能を必要とする場合、それはそれを実装します言語とライブラリはあなたのための仮定をしません。
Cのデータ型付けははるかに緩やかです。これは良いか悪いかは議論の余地がありますが、ポインタの再解釈やファイルから読み取ったデータなどの興味深いことが可能になります。
プログラムを実行するハードウェアについて、もっと注意する必要があります。これは特にCとは関係ありませんが、低レベルのパフォーマンス指向プログラミングのフレーバーとは関係ありません。金属に近づくほど、CPUキャッシュ使用量、メモリフットプリント、デバイスIOコスト、アルゴリズム時間の複雑さなど)に注意を向ける必要があります。たとえば、最終的にターゲットアーキテクチャのキャッシュアクセスパターンが改善されたため、プレーンアレイと線形検索はバイナリ検索ツリーよりも高速であることがプロファイリングされました。
コードだけでなく、データについてもっと意識する必要があります。プログラムの目的はデータを変換することですが、高レベルのインターフェイスを作成するときにコードと抽象化に夢中になり、コードが実際にデータを処理して他のデータを出力する必要があることを忘れてしまいがちです。データをよく知るほど、コードを最適化しやすくなります データ指向の設計 。
これらは考慮すべきいくつかの興味深い側面です。確かにもっとたくさんありますが、今のところはそれが考えられます。それほど難しくないことを願っています。個人的にはC++の方が好きですが;)
。また、低レベルのパフォーマンス指向プログラミングも非常に楽しいものです。入力すると、まったく新しい方法でプログラミングが表示されます。
keyの違いは次のとおりです。
高レベルの開発を行う場合、主に実際の問題を解決する方法を扱います。 「問題ドメイン」は現実の状況であり、エンティティは現実のエンティティであり、ロジックはアプリケーションロジックです。 (たとえば、「現実の世界」という用語はやや柔軟です。たとえば、World of WarcraftのようなMMORPGを開発している可能性があるため、この場合、世界は現実ではありませんが、そのコンテキスト内では、あなたがいる世界です。本物として扱う。)
低レベルの開発を行う場合、主に、マシンに特定のタスクを可能な限り効率的に実行させる方法を扱います。処理しているエンティティは、ほとんどの場合、メモリブロック、ブロックチェーン、ハッシュ値など、本質的に高度に技術的なものであり、ロジックは実世界とは関係なく、マシンとはすべて関係があります。マシンワードの endianness のような完全にマシン固有の概念、または特定のデバイスと通信できるI/Oポート、およびバイバイのシーケンスを扱うことがよくあります。仕事をするために送る必要があります。
実際のところ、高レベルのコードと低レベルのコードを結びつける場合、実際の変換を必要とせずに、高レベルのエンティティを低レベルのエンティティに変換する(または単に前者を後者として表示する)ことがしばしば有益です。 )これにより、高レベルのコードがマシンの問題に対処する必要がなくなり、低レベルのコードがアプリケーションの問題に対処する必要がなくなります。
したがって、アプリケーションには、たとえば顧客のコレクションがあり、購入した商品の請求やニュースレターの送信など、顧客と同じようなことをして、内部の表現を気にすることなく、コレクション。ただし、低レベルのコードでは、コレクションはオブジェクトへのポインターの固定長配列として表示され、これらを呼び出して自分自身を比較したり、それらを比較したりする以外に、これらのオブジェクトについて何も知らない場合があります。独自のハッシュ値を計算します。あなたは彼らが顧客であることを知っているはずもないし、低レベルのコードで彼らにニュースレターを送るはずもない。
したがって、Cなどの低水準言語を使用していて、「顧客」などのアプリケーションエンティティを処理する必要がある場合、それは間違っています。仕事に間違った言語を使用するように求められました。
経験豊富なCプログラマーであり、C++の経験が少ない(ただし、私は他の人が開始したプロジェクトでコーディングし、C++プロジェクトをゼロから構築したことがない)ので、同じ道を逆方向に進んでいる可能性があります。真ん中のどこかで会うことになるかもしれませんが、私がどこから来たかについて少しお話しすることができます。
確かに、CにはないC++のOOPsie機能があります。名前空間の問題、テンプレートなど、私が使用していないものがあります。私がやったことはすべて、クラスおよびクラス内でインスタンス化されたオブジェクトを使用および作成したことです。そして、他の人々が作成したクラスのコードを修正しました。
つまり、Cプログラマは、多くの重要な点で、完全にOOPコードと同様の構造化コードを記述できます。struct
、typedef
、pointers struct
に、共通のフィールドがある別の構造体にポインタをキャストする機能。共通のフィールドと他のフィールドを明示的にオーバーレイできるunion
もあります。これは、OOP言語で見つかる inheritance によく似ています。
個人的には、C =でプログラミングしたいC++の多くの特定の構文が嫌いです。つまり、「正しい」方法を正確に理解しているCでプログラムするだけです。わからないJavaまたはC#またはその他の変種。
主な違い:
すべてのリソース管理を担当します。ガベージコレクションはなく、さらにスペースが必要な場合にバッファーが自動的に拡張されることもありません。これには文字列管理が含まれます。 Cには文字列型はありません。文字列はchar
の配列として格納されます。文字列を追加する場合は、追加する前にターゲットバッファが十分に大きいことを確認する必要があります。
構造化された例外処理はありません。エラーと例外条件は、関数の戻りコードまたはパラメーターへの書き込み(またはerrno
の設定)によって示されます。 setjmp/longjmp
ライブラリ関数を使用して、一種の一種の偽の例外を作成できますが、せいぜいハックです。
Cは、配列アクセスの境界チェックを行いません。配列外の要素にアクセスするための組み込みの例外はありません。それはとんでもなくあなたが所有していないメモリを破壊するのは簡単です(長年の無数の悪用からわかるように)。
データ型はスマートではありません-配列はそれらの大きさを知りません(ほとんどのコンテキストで「配列らしさ」を失います)。関数ポインタを使用しますが、暗黙のthis
ポインタはありません。操作する構造体インスタンスを各関数に明示的に通知する必要があります)。
コードはクラスではなくモジュールに編成され、各モジュールは型定義、オブジェクト定義、および関数定義で構成されます。モジュール間の継承の概念はありません。個々のデータ項目と関数の可視性は、オールオアナッシングの命題です-「保護された」可視性に相当するものはありません。
配列以外のコンテナタイプはありません。それよりも洗練されたものが必要な場合は、自分でロールするか、コンテナライブラリを見つける必要があります。同様に、標準的なアルゴリズムはありません(std::copy
やstd::foreach
など-繰り返しますが、独自のアルゴリズムを使用する必要があります)。
テンプレート、ジェネリック、またはその他の動的型付けメカニズムはありません。関数や演算子のオーバーロードはありません。すべての型情報は、コンパイル時に認識されている必要があります。
ユーザー定義可能な名前空間はありません。 Cは、ラベル、タグ名、構造体と共用体のメンバー名など、合計4つの名前空間をサポートしています。
is書くことが可能 CのOOコード ;それはlotの仕事です。
Cは、鋭いエッジが露出し、ブレードガードがなく、配線がほつれている、見苦しいテーブルソーと考えると、正しい考え方になります。