web-dev-qa-db-ja.com

Cがそれほど危険なのに、なぜCを使用するのですか?

Cの学習を検討しています。

しかし、「危険」に使用できるのに、なぜC(またはC++)を使用するのでしょうか。

危険とは、ポインタやその他の類似のものを意味します。

スタックオーバーフローの質問 のように、gets関数が危険で使用できないのはなぜですか? です。なぜプログラマーは、JavaまたはPythonまたはVisual Basicのような別のコンパイル済み言語)を使用しないのですか?

133
Tristan
  1. Cは、あなたが考えている他の多くの言語よりも古いものです。プログラミングを「より安全」にする方法について私たちが今知っていることの多くは、Cなどの言語の経験から来ています。

  2. C以降に出てきたより安全な言語の多くは、より大きなランタイム、より複雑な機能セット、仮想マシンに依存して目標を達成しています。その結果、Cはすべての人気のある/主流の言語の中で「最低の共通点」の一部として残っています。

    • Cは比較的小さいため、実装がはるかに簡単な言語であり、最も弱い環境でも適切に実行される可能性が高く、独自のコンパイラや他のツールを開発する必要がある多くの組み込みシステムは、機能的なコンパイラを提供できる可能性が高いCの.

    • Cは非常に小さくシンプルなので、他のプログラミング言語はCのようなAPIを使用して互いに通信する傾向があります。これはおそらく、ほとんどの人がラッパーを介してCと対話するだけであっても、Cが本当に死なない主な理由です。

  3. CおよびC++を改善しようとする「より安全な」言語の多くは、プログラムのメモリ使用量と実行時の動作をほぼ完全に制御できる「システム言語」ではありません。最近はますます多くのアプリケーションがそのレベルの制御を必要としないことは事実ですが、それが必要なケースは常に少数あります(特に、これらのすべてのニースで安全な言語を実装する仮想マシンとブラウザーの内部)。残りの皆んな)。

    今日、CまたはC++よりも安全なシステムプログラミング言語(Rust、Nim、Dなど)がいくつかあります。それらには後知恵の利点があり、ほとんどの場合、そのような細かい制御は不要であることを理解しているため、実際に必要なときに切り替えることができるいくつかの安全でないフック/モード​​を備えた一般的に安全なインターフェースを提供します。

  4. C内でも、実際に発生する潜行性のあるバグの数を大幅に減らす傾向がある多くのルールとガイドラインを学びました。既存のコードが多すぎるため、標準でこれらのルールを遡及的に適用することは一般的に不可能ですが、コンパイラの警告、リンター、およびその他の静的分析ツールを使用して、この種の簡単に防止可能な問題を検出するのが一般的です。これらのツールをフライングカラーで渡すCプログラムのサブセットは、「単なるC」よりもはるかに安全であり、最近の有能なCプログラマーは、それらのいくつかを使用します。


また、難読化されたJavaコンテストを 難読化されたCコンテスト のように面白いものにすることは決してありません。

244
Ixrec

まず、Cはシステムプログラミング言語です。したがって、たとえば、Java仮想マシンまたはPythonインタープリターを作成する場合、それらを書き込むにはシステムプログラミング言語が必要になります。

第2に、CはJavaおよびPythonにはないようなパフォーマンスを提供します。通常、Javaおよび= Pythonは、Cなどの高性能言語で記述されたライブラリを使用して重い作業を行います。

第3に、CはJavaやPythonなどの言語よりもフットプリントがはるかに小さい。これにより、組み込みシステムで使用できるようになり、大規模なランタイム環境やメモリ要求をサポートするのに必要なリソースがない可能性がある。 JavaおよびPythonのような言語の。


「システムプログラミング言語」は、次のような産業用システムを構築するのに適した言語です。現状では、JavaとPythonはシステムプログラミング言語ではありません。「システムプログラミング言語を正確に作るもの」はこの質問の範囲外ですが、システムプログラミング言語は、基盤となるプラットフォームでの作業をサポートする必要があります。

一方(コメントへの応答として)、システムプログラミング言語はnotをセルフホスティングにする必要があります。この問題は、元の質問で「なぜ人々はCを使用するのか」と尋ね、最初のコメントは「なぜCのような言語が必要なのか」と尋ねたためです。PyPyがあると、PyPy does実際にはCを使用します。そのため、元々は質問に関連していましたが、残念ながら(そして混乱して)「セルフホスティング」は実際にはこの回答には関連していません。育ててごめんなさい。

つまり、JavaおよびPythonは、その主要な実装が解釈されるため、またはネイティブにコンパイルされた実装がセルフホストされないためではなく、システムプログラミングには適していません。 。ただし、基盤となるプラットフォームでの作業に必要なサポートを提供していないため。

41
comingstorm

さらに別の回答を追加して申し訳ありませんが、既存の回答のいずれかが最初の文を直接説明しているとは思いません:

「Cの学習を検討しています」

どうして?今日Cで通常使用されている種類のことを行いますか(デバイスドライバー、VM、ゲームエンジン、メディアライブラリ、組み込みシステム、OSカーネルなど)?

はいの場合は、そうです。興味のある方に応じて、CまたはC++を確実に学習してください。高水準言語が何をしているかをより深く理解できるように、それを学習しますか?

次に、安全上の懸念について言及します。後者を行うために、安全なCについてdeepを理解する必要は必ずしもありません。これは、高水準言語のコード例が本番環境に準備されていないGistを提供するのと同じです。

Gistを取得するためのCコードを記述します。それを棚に戻します。 production Cコードを記述しない限り、安全性についてあまり心配しないでください。

30
Jared Smith

これは膨大な数の回答が含まれる巨大な質問ですが、短いバージョンでは、各プログラミング言語はさまざまな状況に特化しています。たとえば、Web用のJavaScript、低レベルのもの用のC、Windows用のC#などです。プログラミングを理解したら、何をしたいかを知り、選択するプログラミング言語を決定するのに役立ちます。

最後のポイントである、なぜJava/PythonよりもC/C++に取り組むかは、多くの場合速度に影響します。私はゲームを作っていますが、Java/C#は最近ゲームを実行するのに十分な速度に達しています。結局のところ、ゲームを60フレーム/秒で実行させ、ゲームに多くのことを行わせたい場合(レンダリングは特にコストがかかります)、コードをできるだけ速く実行する必要があります。 Python/Java/C#/「インタプリタ」上で実行される他の多くは、メモリやガベージコレクションの管理など、C/C++が処理しないすべての面倒な処理を行うソフトウェアの追加レイヤーです。この余分なオーバーヘッドにより処理速度が低下するため、目にするほぼすべての大規模なゲームは(とにかく過去10年間で)CまたはC++で行われました。例外があります。UnityゲームエンジンはC#*を使用し、MinecraftはJavaを使用しますが、例外であり、ルールではありません。一般に、インタープリター型言語で実行される大きなゲームは、その言語の速度の限界を押し上げています。

* UnityもすべてC#ではありません。その大部分はC++であり、ゲームコードにC#を使用するだけです。

[〜#〜] edit [〜#〜]私がこれを投稿した後に表示されたコメントの一部に応答するために:おそらく私はあまりに単純化しすぎていたので、私は全体像を与えていました。プログラミングでは、答えは決して単純ではありません。 Cにはインタープリターがあり、Javascriptはブラウザーの外で実行でき、C#はMonoのおかげでほとんど何でも実行できます。さまざまなプログラミング言語がさまざまなドメインに特化していますが、プログラマーはどこかでおそらく、どのようなコンテキストでもあらゆる言語を実行する方法を理解していました。 OPはプログラミングをあまり知らないように見えたので(私の側の仮定、私が間違っているとすみません)、私の答えを単純に保つようにしていました。

C#がC++とほぼ同じ速さであるというコメントについては、重要なWordはほぼそろっています。私が大学にいたとき、私たちは多くのゲーム会社をツアーしました、そして私の教師(私たちがC#からC++に一年中移動することを奨励していた)はすべての会社のプログラマーにC#よりもC++に行く理由を尋ねましたC#は遅すぎると述べました。一般に高速で実行されますが、ガベージコレクターは実行時に制御できないためパフォーマンスを低下させる可能性があり、推奨されたときに実行したくない場合は無視する権利があります。高性能にするために何かが必要な場合は、そのような予測できないものは必要ありません。

「速度に達しました」というコメントに対応するために、ええ、C#の速度向上の多くは、より優れたハードウェアによるものですが、.NETフレームワークとC#コンパイラーが改善されたため、速度が向上しています。

「ゲームはエンジンと同じ言語で書かれている」というコメントについては、状況によります。いくつかはありますが、多くは言語のハイブリッドで書かれています。 UnrealはUnrealScriptとC++を実行でき、UnityはC#JavascriptとBooを実行します。CまたはC++で記述された他の多くのエンジンはPythonまたはスクリプト言語としてLuaを使用します。そこに簡単な答えはありません。

そして、「ゲームが200fpsか120fpsのどちらで実行されるかを気にする」というバグを見つけただけで、ゲームが60fpsよりも高速で実行されている場合は、平均的なモニターでは更新されないため、CPU時間を浪費している可能性があります。速い。いくつかのハイエンドおよび新しいものはありますが、それは標準ではありません(まだ...)。

「テクノロジーの数十年を無視する」という発言については、私はまだ20代前半にいるので、逆に外挿しているときは、主に年配の経験豊富なプログラマーが私に言ったことをエコーし​​ています。明らかに、このようなサイトで争われることになりますが、検討する価値はあります。

14
Cody

「ポインタがある」のでCは安全ではないと主張するのはおかしいです。反対は真です:JavaおよびC#は実質的にポインタのみ(非ネイティブ型の場合)を持っています。Javaで最も一般的なエラーはおそらくNullポインタ例外です(cf. https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare )2番目に多いエラーは、おそらく解放されない未使用のオブジェクト(たとえば、閉じたダイアログは破棄されません)は、メモリフットプリントが増大し続ける長期実行プログラムにつながります。

C#とJavaをより安全にし、2つの異なる方法でより安全にする2つの基本的なメカニズムがあります。

  • ガベージコレクションにより、プログラムが破棄されたオブジェクトにアクセスしようとする可能性が低くなります。これにより、プログラムが予期せず終了する可能性が低くなります。 Cとは対照的に、JavaおよびC#は、デフォルトで非ネイティブデータを動的に割り当てます。これにより、プログラムロジックは実際により複雑になりますが、組み込みのガベージコレクションは(代償として)かかります。難しい部分に。

最近のC++のスマートポインターにより、プログラマーはその作業を簡単に行うことができます。

  • JavaとC#は、精巧なランタイムによって解釈/実行される中間コードにコンパイルされます。ランタイムはプログラムの不正なアクティビティを検出できるため、これによりセキュリティのレベルが追加されます。プログラムが安全にコーディングされていない場合でも(両方の言語で可能です)、それぞれのランタイムにより、理論上はシステムへの「侵入」が防止されます。
    ランタイムは、たとえばから保護しません。バッファオーバーランを試みましたが、理論的にはそのようなプログラムの悪用を許可していません。対照的に、CおよびC++では、エクスプロイトを防ぐためにプログラマーは安全にコーディングする必要があります。これは通常、すぐには達成されませんが、レビューと反復が必要です。

複雑なランタイムもセキュリティ上のリスクがあることは注目に値します。新しく発見された安全性の問題により、Oracleは数週間ごとにJVMを更新しているようです。もちろん、JVMを検証することは、単一のプログラムよりもはるかに困難です。

したがって、精巧なランタイムの安全性は曖昧であり、ある程度誤解を招きます。平均的なCプログラムは、レビューと反復により、かなり安全にすることができます。あなたの平均Javaプログラムは、JVMと同じくらい安全です;つまり、実際にはそうではありません。決してありません。

リンクするgets()に関する記事は、コア言語ではなく、今日では異なる方法で行われるライブラリの歴史的な決定を反映しています。

「安全」には速度がかかるため、「安全」な言語の実行速度は遅くなります。

CやC++のような「危険な」言語を使用する理由を尋ね、誰かにビデオドライバーなどをPythonまたはJavaなどで)書いてもらい、「安全性」についてどのように感じているかを見てもらいます。 )

真剣に、しかし、ピクセルやレジスターなどを操作できるようにするには、マシンのコアメモリに近い必要があります... JavaまたはPythonパフォーマンスに値するあらゆる速度でこれを行うことはできません... CとC++の両方で、ポインタなどを使用してこれを行うことができます...

10
Wintermut3

上記のほかにも、Cを他の言語の共通ライブラリとして使用する、かなり一般的な使用例が1つあります。

基本的に、ほぼすべての言語にCへのAPIインターフェースがあります。

簡単な例として、Linux/IOS/Android/Windows用の一般的なアプリケーションを作成してみましょう。そこにあるすべてのツールに加えて、最終的にCでコアライブラリを実行し、各環境のGUIを変更しました。

  • IOS:ObjectiveCはCライブラリをネイティブで使用できます
  • Android:Java + JNI
  • Linux/Windows/MacOS:GTK/.Netを使用すると、ネイティブライブラリを使用できます。 Python、Perlを使用している場合、RubyそれぞれにネイティブAPIインターフェースがあります(JNIを使​​用したJava)。

私の2セント

9
Nito

Cの根本的な問題は、その名前が、構文は同じだがセマンティクスが大きく異なる複数の方言を表すために使用されることです。一部の方言は、他よりもはるかに安全です。

Dennis Ritchieによって最初に設計されたCでは、Cステートメントは通常、予測可能な方法で機械語命令にマッピングされます。 Cは、符号付き算術オーバーフローなどが発生したときに異なる動作をするプロセッサ上で実行できるため、算術オーバーフローが発生した場合にマシンがどのように動作するかを知らなかったプログラマは、そのマシンで実行されるCコードがどのように動作するかを知りませんが、マシンが特定の方法で動作することがわかっている場合(たとえば、サイレント2の補数のラップアラウンド)、そのマシンでの実装は通常、同様に動作します。 Cが高速であるとの評判を得た理由の1つは、エッジケースシナリオでのプラットフォームの自然な動作がニーズに適合することをプログラマーが知っていた場合、そのようなシナリオを生成するコードをプログラマーまたはコンパイラーが作成する必要がないことでした。 。メモリにアクセスするためにポインタを使用するコードは、ポインタが使用してはならないものにアクセスするために決して使用されないことを確認することが重要でした。これは通常、ポインタを含む計算がオーバーフローしないことを確認する必要がありますが、算術などについてのパラノイアは必要ありません。他のコンテキストではオーバーフローします。

残念ながら、コンパイラの作成者は、標準がそのような場合に実装が何をしなければならないかについて要件を課さないため(予測どおりに動作しない可能性のあるハードウェア実装を可能にすることを意図した寛容さ)、コンパイラは自由に法則を無効にするコードを生成する必要があるとの見方をしています時間と因果関係の。

次のようなものを検討してください:

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

ハイパーモダンな(しかしファッショナブルな)コンパイラの理論では、コンパイラは "QUACK!"を出力する必要があることを示唆しています。無条件に、条件が偽である場合は常に、プログラムは結果が無視される乗算を実行する未定義の動作を呼び出すことになります。標準では、このような場合にコンパイラーが好きなことを実行できるようにするため、コンパイラーは "QUACK!"を出力できます。

Cは以前はアセンブリ言語より安全でしたが、ハイパーモダンコンパイラを使用する場合はその逆になります。アセンブリ言語では、整数オーバーフローにより計算が無意味な結果をもたらす可能性がありますが、ほとんどのプラットフォームではその影響の範囲になります。いずれにしても結果が無視される場合は、オーバーフローは問題になりません。ただし、ハイパーモダンCでは、通常は「良性」の未定義の動作(計算での整数オーバーフローが無視されるなど)であっても、任意のプログラムが実行される可能性があります。

7
supercat

「危険」とは何ですか?

Cが「危険」であるという主張は、言語の炎上戦争で頻繁に話題になる点です(ほとんどの場合、Javaと比較して)。ただし、この主張の証拠は不明です。

Cは特定の機能セットを持つ言語です。これらの機能の一部は、他のタイプの言語では許可されない特定のタイプのエラーを許可する場合があります(Cのメモリ管理のリスクは通常強調されます)。ただし、これは、Cが他の言語よりも危険であるoverallという引数と同じではありません。この点について説得力のある証拠を提供している人を私は知りません。

また、「危険」は状況によって異なります。何をしようとしているか、どのようなリスクが心配ですか?

多くのコンテキストでは、Cは高水準言語よりも「危険」であると考えます。これは、基本的な機能を手動で実装する必要があり、バグのリスクが高まるためです。たとえば、他の言語にはこれを非常に簡単にする機能があるため、基本的なテキスト処理を行ったり、CでWebサイトを開発したりすることは、通常はばかげています。

ただし、CおよびC++は、ミッションクリティカルなシステムで広く使用されています。これは、ハードワードを直接制御する小さな言語は、そのコンテキストでは「安全」と見なされるためです。から 非常に優れたスタックオーバーフローの回答

CおよびC++は、このタイプのアプリケーション用に特別に設計されたわけではありませんが、いくつかの理由により、組み込みおよび安全性が重要なソフトウェアに広く使用されています。注目すべき主な特性は、メモリ管理の制御(これにより、たとえばガベージコレクションの必要性を回避できる)、シンプルで十分にデバッグされたコアランタイムライブラリ、および成熟したツールのサポートです。今日使用されている多くの組み込み開発ツールチェーンは、1980年代と1990年代に最初に開発されました。これは現在のテクノロジーであり、当時普及していたUnix文化に由来するため、これらのツールはこの種の作業で引き続き人気があります。

エラーを回避するために手動のメモリ管理コードを注意深くチェックする必要がありますが、ガベージコレクションに依存する言語では利用できない、アプリケーションの応答時間をある程度制御できます。 CおよびC++言語のコアランタイムライブラリは比較的シンプルで成熟しており、十分に理解されているため、利用可能な最も安定したプラットフォームの1つです。

5
user82096

既存の回答に追加するには、プロジェクトのPythonまたはPHPを選択するのは、比較的安全であるためです) 。しかし、誰かがそれらの言語を実装する必要があり、実装した場合、おそらくCで実装することになります(または、まあ、そのようなものです)。

だからこそ、人々はC —を使用して、あなたが使用したい、それほど危険ではないツールを作成します。

歴史的な理由。新しいコードを書くことはあまりありませんが、主に何十年も実行されてきた古いものを維持し、拡張することができます。私はそれがFortranではなくCであることを嬉しく思います。

「しかし、なぜYをしているのに、なぜこのひどいXをするのですか?」ええと、Xは私が持っている仕事であり、それは手形を非常にうまく支払います。私はたまにYをやったことがあり、楽しかったですが、Xはほとんどの人がやっていることです。

5
RedSonja

質問の言い換えをさせてください:

[ツール]の学習を検討しています。

しかし、[危険]に使用できるのに、なぜ[ツール](または[関連ツール])を使用するのでしょうか。

プログラミング言語を含むあらゆる興味深いツールが危険に使用される可能性があります。あなたは学習より多くのことができるのでdoより多くのことができます(そして、ツールを使用するときに作成される危険が少なくなります)。特に、そのツールを学習して、そのツールが得意なことを実行できるようにします(そして、そのツールがあなたが知っているツールの中で最高のツールであるときを認識するかもしれません)。

たとえば、直径6 mm、深さ5 cmの円筒形の穴を木のブロックに配置する必要がある場合、ドリルはLALRパーサーよりもはるかに優れたツールです。これらの2つのツールがわかっている場合は、どちらが適切なツールであるかがわかります。ドリルの使い方をすでに知っている場合は、出来上がり!.

Cは単なる別のツールです。一部のタスクの方が他のタスクよりも優れています。ここでの他の答えはこれに対処します。 Cを習得すると、それが適切なツールである場合とそうでない場合がわかるようになります。

2
Eric Towers

Cの学習を検討しています

Cを学習しない特別な理由はありませんが、C++をお勧めします。これは、Cが行うことの多く(C++がCのスーパーセットであるため)を提供し、大量の「エクストラ」を備えています。 C++の前にCを学ぶ必要はありません-それらは事実上別々の言語です。

別の言い方をすると、Cが木工ツールのセットである場合、おそらく次のようになります。

  • ハンマー
  • 手のこぎり
  • ハンドドリル
  • ブロックサンダー
  • のみ(たぶん)

これらのツールで何でも構築できますが、何かNiceには、多くの時間とスキルが必要になる可能性があります。

C++は、ローカルハードウェアストアにあるパワーツールのコレクションです。

始めるために基本的な言語機能に固執する場合、C++には追加の学習曲線が比較的ほとんどありません。

しかし、「危険」に使用できるのに、なぜC(またはC++)を使用するのでしょうか。

イケアの家具が欲しくない人もいるからです。 =)

真面目な話ですが、CやC++より「上位」の多くの言語には、特定の側面で(潜在的に)「使いやすい」ものがあるかもしれませんが、これは必ずしも良いことではありません。何かを行う方法が気に入らない場合や、機能が提供されていない場合は、それについてできることはほとんどありません。一方、CおよびC++は十分な「低レベル」言語機能(ポインタを含む)を提供し、多くのことに直接(特にハードウェアまたはOS的に)アクセスしたり、自分で構築したりすることができます。実装された言語。

より具体的には、Cには次の一連の機能があり、多くのプログラマにとって望ましいものになっています。

  • 速度-長年にわたって比較的単純でコンパイラが最適化されているため、本来非常に高速です。また、多くの人々が言語を使用する際に特定の目標への多くのショートカットを理解しているため、言語がさらに高速になる可能性があります。
  • Size-速度について記載されているものと同様の理由で、Cプログラムは非常に小さくできます(実行可能サイズとメモリ使用量の両方に関して)。メモリが限られている環境(つまり、組み込みまたはモバイル)に適しています。
  • 互換性-Cは長い間使用されており、誰もがツールとライブラリを持っています。言語自体もうるさいわけではありません-プロセッサが命令を実行し、メモリを保持することを期待しています。

    さらに、 Application Binary Interface(ABI) として知られているものがあります。要するに、これはプログラムがマシンコードレベルで通信する方法であり、 アプリケーションプログラミングインターフェイス(API) よりも優れている場合があります。 C++などの他の言語はABIを持つことができますが、通常、これらはCのものよりも統一されていない(合意されている)ため、何らかの理由でABIを使用して別のプログラムと通信する場合、Cは優れた基礎言語になります。

なぜプログラマーは、JavaまたはPythonまたはVisual Basicのような別のコンパイル済み言語)を使用しないのですか?

効率(およびメモリに比較的直接アクセスしないと実装できないメモリ管理スキーム)。

ポインタでメモリに直接アクセスすると、メモリの小さな穴にゼロとゼロを直接配置できるため、OLの先生がおもちゃを配るのを待つ必要がない場合に、多くのきちんとした(通常は迅速な)トリックが導入されます。プレイタイムにそれらを再びすくい上げます。

要するに、ものを追加するとラグが生じる可能性があるか、そうでなければ望ましくない複雑さが導入されます。

スクリプト言語とその同類については、C(または任意のコンパイル済み言語)がネイティブで実行するのと同じくらい効率的に実行するために二次プログラムを必要とする言語を取得するために一生懸命努力する必要があります。オンザフライインタープリターを追加すると、別のプログラムをミックスに追加するため、本質的に実行速度が低下し、メモリ使用量が増加する可能性があります。プログラムの効率は、元のプログラムコードをどれだけ上手に(不十分に=)書いたかと同様に、この2次プログラムの効率に依存します。言うまでもなく、プログラムは多くの場合、実行する2番目のプログラムに完全に依存しています。その2番目のプログラムは、特定のシステムに何らかの理由で存在しませんか?ノーコード。

実際、anything "extra"を導入すると、コードが遅くなったり複雑になったりする可能性があります。 「怖いポインタのない」言語では、他のコードが背後でクリーンアップするのを常に待っているか、そうでなければ「安全な」方法を見つけ出す-プログラムはまだポインターで行うのと同じメモリーアクセス操作を行う。あなたはそれを扱っているだけではありません(そのため、それをf * ckできない、genius = Pです)。

危険とは、ポインタやその他の類似のものを意味します。 [...]スタックオーバーフローの質問のように gets関数が非常に危険で使用できないのはなぜですか?

受け入れられた答えによれば:

「1999年のISO C標準までは引き続き言語の正式な部分でしたが、2011年の標準によって正式に削除されました。ほとんどのC実装では引き続きサポートされていますが、少なくともgccはそれを使用するコードに対して警告を発行します。」

言語で何かを行うことができるので、それはしなければならない必要があるという考えはばかげています。言語には修正される欠陥があります。古いコードとの互換性の理由から、この構造は引き続き使用できます。しかし、プログラマにget()の使用を強制することは(おそらく)ありません。実際、このコマンドは本質的に安全な代替手段に置き換えられました。

さらに言えば、gets()の問題は、それ自体がポインタの問題ではありません。これは、メモリを安全に使用する方法を必ずしも認識していないコマンドの問題です。抽象的には、これはすべてのポインタの問題です-想定外のものを読み書きすることです。これはポインターの問題ではありません。ポインタの実装に問題があります。

明確にするために、意図していないメモリ位置に誤ってアクセスするまで、ポインタは危険ではありません。それでも、コンピュータが溶けたり爆発したりするとは限りません。ほとんどの場合、プログラムは(正しく)機能しなくなります。

とはいえ、ポインタはメモリの場所へのアクセスを提供し、データと実行可能コードはメモリ内に共存するので、メモリを正しく管理したいという偶発的な破損の危険性は十分にあります。

その時点まで、真のダイレクトメモリアクセス操作は、一般的に数年前よりも一般的にメリットが少ないため、C++などの非 ガベージコレクション言語 でさえ、 スマートポインタ は、メモリ効率と安全性のギャップを埋めるのに役立ちます。

要約すると、ポインタが安全に使用されている限り、ポインタを恐れる理由はほとんどありません。サウスパークのスティーブ「ザクロコダイルハンター」アーウィンのバージョンからヒントをもらいましょう- クロックスの尻穴に親指を突き刺さないでください

1
Anaksunaman

いつものように、プログラミング言語は問題解決の結果にすぎません。実際にCだけでなく、さまざまな言語(およびGUIツールやコマンドインタープリターなど、コンピューターをプログラミングする他の方法)を学習して、問題を解決するときに適切なツールボックスを使用する必要があります。

問題がJavaデフォルトライブラリに含まれているものに適している場合があります。そのような場合、Javaを選択して、 。他の場合では、.NETランタイムではるかに簡単な何かをWindowsで実行する必要がある場合があるため、C#またはVBを使用できます。問題を解決するグラフィカルツールまたはコマンドスクリプトがある場合、これらを使用することができます。複数のプラットフォームでGUIアプリケーションを作成する必要があるかもしれませんJavaは、JDKに含まれているライブラリを前提として、オプションである可能性がありますが、1つのターゲットプラットフォームにはJREなので、多分代わりにCとSDL(または同様のもの)を選択します。

Cは一般的で小型で高速であり、マシンコードにコンパイルされるため、このツールセットでは重要な位置を占めています。また、Sunの下のすべてのプラットフォームでサポートされています(ただし、再コンパイルは必要です)。

要するに、できる限り多くのツール、言語、パラダイムを学ぶ必要があります。

「私はXプログラマーです」(X = C、C++、Javaなど)という考え方から離れてください。

「私はプログラマーです」を使用してください。

プログラマーは、ワークロードを実行するようにマシンに指示することにより、問題を解決し、アルゴリズムを設計します。話の終わり。これは言語とは無関係です。あなたの最も重要なスキルは問題解決と構造化された問題の論理的な分解です。言語スキル/選択は常に二次的であり、そして/または問題の性質の結果です。

Cに興味がある場合の興味深いパスは、Goでスキルセットを拡張することです。 Goは、ガベージコレクションとインターフェイスを備えた、本当に改善されたCであり、Nice組み込みのスレッドモデル/チャネルであり、Cの多くの利点(ポインター演算やマシンコードへのコンパイルなど)ももたらします。

1

それはあなたがそれをどうするつもりかによって異なります。 Cはアセンブリ言語の代替として設計され、機械語に最も近い高水準言語です。したがって、サイズとパフォーマンスのオーバーヘッドが低く、フットプリントが小さく、基盤となるハードウェアに近づく必要があるシステムプログラミングやその他のタスクに適しています。

0

最も効率的なアロケーターとデータ構造を効果的に実装するためにしばしば必要となる、データの生の同種のコレクションとしてのメモリのビットとバイトのレベルで作業しているとき、安全性はありません。安全性は、主にデータ型に関連する強力な概念であり、メモリアロケータはデータ型では機能しません。ビットとバイトを使用して、同じビットとバイトをプールし、1つのデータ型を表し、後で別のデータ型を表す可能性があります。

その場合、C++を使用してもかまいません。あなたはまだふりかけるだろうstatic_castsキャストするコード全体でvoid*ポインタとビットとバイトの操作、およびこのコンテキストでの型システムの尊重に関連する面倒な問題に対処するだけのCよりも、単純な型システムでmemcpyビットとバイトを自由に使用できます型システムを気にする必要はありません。

実際、C++の型システムをブルドーザ化して次のようなことをすることができるので、Cよりも危険なコードを書かずに、ビットとバイトの低レベルのコンテキストで、全体的に安全な言語であるC++で作業することはしばしば困難です。 vptrsを上書きし、適切なタイミングでコピーコンストラクターとデストラクターを呼び出せない。これらのタイプを尊重して新しい配置を使用し、dtorを手動で呼び出すなどの適切な時間をとると、RAIIが実用的ではなく、例外を達成するには低レベルのコンテキストで例外処理の世界にさらされることになります。このような低レベルのコンテキストでの安全性は非常に困難です(ほぼすべての関数がすべての可能性をスローしてキャッチし、何も起こらなかったかのように分割できないトランザクションとして副作用をロールバックできるように見せかける必要があります)。 Cコードは、Cでインスタンス化されたデータ型を、型システムに違反したり、未定義の動作を引き起こしたり、例外を発生させたりすることなく、単なるビットとバイトとして扱うことができると「安全に」想定できることがよくあります。

そして、そのようなアロケータを、ここで「危険」になることを許可しない言語で実装することは不可能です。それらが提供するアロケーター(CまたはC++で実装される可能性が最も高い)に依存し、それが目的に十分適していることを期待する必要があります。また、ほとんどの場合、特定の目的に適したより効率的で一般的ではないアロケータとデータ構造がありますが、目的に合わせて特別に調整されているため、適用範囲ははるかに狭くなります。

彼らはもともとCまたはC++で実装されたコードを呼び出すことができるため、ほとんどの人はCまたはC++のようなものを必要としません。個々のピクセルをループする最低レベルではそれほど革新的ではないが、Cに既に実装されている既存の画像処理関数のライブラリを使用するだけの画像プログラムをつなぎ合わせるなど、多くの人が高レベルで革新することから利益を得るかもしれませんが、これまでにない非常にフレンドリーなユーザーインターフェイスとワークフローを提供します。その場合、ソフトウェアの目的が低レベルのライブラリに高レベルの呼び出しを行うことだけである場合(「この画像全体を処理します。ピクセルごとではなく、何かを実行します」)、次にCでそのようなアプリケーションの作成を開始しようとすることさえ、おそらく時期尚早の最適化かもしれません。

しかし、これまでにない新しい画像フィルターのように、低レベルでデータにアクセスするのに役立つ低レベルで何か新しいことを行っている場合、リアルタイムでHDビデオを処理するには十分高速である必要があります。少し危険です。

これを当たり前のことと考えるのは簡単です。 Pythonを使用して3Dビデオゲームを作成することがどのように実行可能であるかを誰かが指摘したFacebookの投稿を覚えています。低レベル言語が時代遅れになりつつあり、それはまともな見た目のゲームでした。しかし、Pythonは、Cに実装されたライブラリに高レベルの呼び出しを行って、すべての重い作業を行いました。既存のライブラリに高レベルの呼び出しを行うだけでは、Unreal Engine 4を作成できません。 。Unreal Engine 4 isライブラリ。ライティングからそのノードブループリントシステムに至るまで、他のライブラリやエンジンには存在しなかったあらゆる種類の処理を行い、その場でコードをコンパイルして実行できます。エンジン/コア/カーネルの低レベルで革新したい場合は、低レベルにする必要があります。すべてのゲーム開発者が高レベルの安全な言語に切り替えた場合、Unreal Engine 5、6、7は存在しません。 。次世代のエンジンを開発するために必要なレベルで革新できないため、40年後もアンリアルエンジンをまだ使用している人がいるでしょう。 e古いものに高レベルの呼び出しを行うだけ。

0
user204677