Cからは、より高いレベルの言語では学べない原則は何ですか?[閉まっている]


11

Cはプログラミングの背後にある原則を学ぶのに適した言語だと思います。Rubyのような高レベルな言語から「魔法のように」なっている低レベルの言語で何を学べると思いますか?


2
とにかく、魔法、またはその一部を学びます。Cは「金属により近い」ため、金属について詳しく学びます。
ロバートハーヴェイ

1
C ++に出会うまで、参照の概念を完全には理解していませんでした。
user6245072

6
Cは、スタックオーバーフローが実際に何であるかを教えてくれます。難しい方法。
david25272

1
新しいプログラマーが古き良きPascalと構造化プログラミングを学ぶことから始めることを望みます。論理的かつ構造的に自分を表現することを学びます。
ベント

2
CとC ++だけが教えてくれることは、コンパイラが最悪の敵だということです。
-CodesInChaos

回答:


9

Cに存在し、高レベル言語にも存在しない原則は、コンピューターサイエンスの一般的な抽象的な意味ではありません。コンピューターサイエンスはすべてアルゴリズムに要約されており、すべてのアルゴリズムはCのようにチューリング完全な任意の言語で実装できます。

Cが高レベル言語から離れていることの違いは、マシンコードがCから離れていることの違いに似ています。マシンとコードの関係。

高級言語でコードを書くとき、コードがマシンとどのように相互作用するかについて(一般的に)気にする必要はありません。言語自体が定義する仮想マシンは、コード実行のこれらの側面の多くを隠します。

Cでは、プログラムとメモリの相互作用は最前線にあります。単にヒープの使用を管理する必要があるだけでなく、スタックとのコードの相互作用、コードのメモリへのアクセスがコードの動作とパフォーマンスにどのように影響するか(メモリアクセスの順序さえも)が含まれます間違った時間に間違ったメモリを読み取ると、パフォーマンスが効果的に低下する可能性があるため、注意を逸らすことができます。

高レベル言語では、これらのことは単純ではありません。メモリは、ユーザーの知らないうちに、場合によってはプロンプトなしで割り当ておよび割り当て解除されます。ほとんどの場合、これは単純に制御できません。ほとんどのメモリ割り当ての時期、場所、方法、および理由は、単にあなたから隠されています。

同様に、マシンコードまたはアセンブリコードを記述すると、さらに詳細が前面に表示されます。ほとんど何もあなたの視野の外に残されません。コードは、すべての割り当て、すべてのリソース、通過するすべてのデータを認識して書かなければなりませんCPUのレジスタを介して-高度な言語から難解なほどに除去された知識。


6
このような議論でチューリング完全性に言及する理由がよくわかりません。チューリング完全性は、このコンテキストでは意味がありません。Cはその点で他のプログラミング言語と違いはないので、Cに切り替えることでチューリング完全性について学ぶことは何もありません。チューリング完全性が関係するのは、CSSやHTMLのようなチューリング完全でないものについて議論するときだけです。地獄、あなたが十分に目を細めれば、それらさえチューリング完全です。より意味のある質問は、ユーザビリティに
ロバートハーベイ

3
@RobertHarvey私のポイントは、言語が合理的な最小の計算能力を持っている限り、その「レベル」はこの文脈で重要な唯一のことであるアルゴリズムの観点からは無関係になるということです。
greyfade

3
なぜなら、あなたはOPの質問にとってまったく重要ではない点を指摘しているからです。プログラマーは常にこれを行います。「チューリング完全」というフレーズを実際に使用しているように、実際の意味でいくつかの意味のある使い方があります。重要ではないこと
ロバートハーヴェイ

2
<皮肉>生物学は化学の特別な場合であり、これは素粒子物理学の特別な場合です。素粒子物理学を知っていれば、生物学から学べることは何もありません。そうですか</ irony>
Florian F

3
Cは単に割り当てと割り当て解除を明示的に行うことを要求するだけですが、「高レベル」言語のように抽象的なマシンに関係しています-物理的な(例えば)x86マシンはまだCの範囲外です。 Cコードを解釈する完全にサンドボックス化されたVMを作成できますが、物理マシンのメモリ割り当てを制御することはできず、100%準拠の実装である可能性があります。
セオドロスチャツィジアンナキス

13

Cはプログラミングの背後にある原則を学ぶのに適した言語であることを知っています。

同意しません。Cには、プログラミングの背後にある原理を学ぶにはあまりにも多くの機能がありません。抽象化を作成するためのCの機能はひどく、抽象化はプログラミングの背後にある重要な原則の1つです。

ハードウェアがどのように機能するのか、したがって機械に対する機械的な同情を知りたい場合は、機械語(命令セットアーキテクチャとも呼ばれます)を学習し、最新のCPUのキャッシュ構成も学習する必要があります。アセンブリ言語はお勧めしません。ハードウェアの指示を理解するだけなので、コンパイラが生成するものを理解できます。

プログラミングの原則を学びたい場合は、Java、C#、Swiftなどの最新の言語、またはRustなどの他の多数の言語を使用してください。また、関数型を含むさまざまな種類のプログラミングパラダイムを研究します。


12
Cは抽象化の作成に適しています。あなたは、Cのメソッドを書くことができ、あなたはC.何Cが使用して構築されているC.全体のオペレーティングシステムで構造などのデータをパッケージ化することができないが、オブジェクト指向がされているもののすべての人の「現代」という考えを満たすさで良いはずな外観にしますお気に入り。
ロバートハーベイ

4
そうでもない。CはASMよりもかなり高いレベルです。クラスを使用することを期待しないでください。そうする方法はありますが、もしあなたがそんなに傾いているなら。
ロバートハーベイ

4
コメントの「アセンブラ」を「Brainfuck」に置き換えてください。これはまだ当てはまるはずです。しかし、それは私がすぐにBrainfuckを使用するつもりであることを意味しません。
ロバートハーベイ

6
Cの機能に関する議論は、クラス(およびガベージコレクションなど)が新しいプログラマー(私はそうではない)を教えるために必要な要素であると信じている場合にのみメリットがあります。ここでは、クラスレス言語でクラスを使用しようとする人は誰もいません。
ロバートハーベイ

5
@Robert、私の主張は、Cは低レベル言語であるため、プログラミングの原則を理解するのに最適な言語ではないことです。これはアセンブラについても言えますが、それは低レベル言語であるという意味ではありませんそれらは、プログラミングの「真の」原則に何らかの形で近づいています。代わりに、これらの言語はハードウェアとオペレーティングシステムの動作を理解するのに優れており、それが興味のある場合は、命令セットアーキテクチャとマシン言語を学習する際に、最下位レベルまでスキップすることをお勧めします。それ以外の場合は、選択する言語がたくさんあります。
エリックエイド

8

Cおよび(Abstract)Machine

ほとんどのプログラミング言語は、抽象マシンの観点から説明されています。次に、コンパイラー、リンカー、アセンブラー、インタープリター、静的アナライザー、中間言​​語、ハードウェアなどのツールのセットを使用して実装され、プログラムによって観察されるように、少なくとも抽象マシンの予想されるすべての動作を尊重する結果をまとめて生成します。

Cは上記の規則の例外ではありません。それは、実際のハードウェアの概念を持たない抽象的なマシンの観点から説明されています。

そのため、Cがコンピューターの実際の動作を教えると人々が言うとき、彼らが通常意味するのは、CがCの動作を教えることです。しかし、Cはシステムプログラミングに非常に普及しているため、多くの人がCをコンピューター自体と混同し始めることは理解できます。そして、個人的には、Cがどのように機能するかを知ることは、コンピューター自体がどのように機能するかを知ることよりも重要であると言っているほどです。

それでも、Cとコンピューター異なるものです。実際のハードウェアは実際には複雑です-C仕様を子供向けの本のように読む方法で。ハードウェアの動作に興味がある場合は、いつでもマニュアルを検索して、アセンブラーでコードの記述を開始できます。または、自分でハードウェアを設計できるように、いつでもデジタル回路について学び始めることができます。(少なくとも、Cのレベルが高いことに感謝します。)

どうやって学ぶの?そして、どのよう学びますか?

さて、実際にハードウェアについて学ぶにはC以外のことも含まれます。しかし、Cは今日プログラマーに何か他のものを教えることができますか?

状況によると思います。

  • 多くの場合、複数の方法でそれを提供し、それを奨励する環境で作業することで、より良い概念を学ぶことができると言う人がいます。
  • 概念を提供していない環境で作業することで、概念をよりよく学習できると言う人もいます。代わりに自分でそれを構築する必要があります。

これらの可能性のいずれかを選択するのに速すぎないでください。私は長年コードを書いてきましたが、どちらが正解なのか、正解が2つのうちの1つなのか、この問題に関して正解のようなものがあるのか​​はまだわかりません。

おそらく最終的に両方のオプションを、説明した順序で大まかに適用する必要があると私はやや信じています。しかし、これは本当に技術的な問題ではないと思います。ほとんど教育的なものだと思います。すべての人が著しく異なる方法で学習するようです。

Cのみ

少なくとも私が提案した2番目のオプションを使用して上記の質問に答えた場合は、すでにいくつかの答えがあります。高級言語で学習できるものはすべて、CまたはミックスにCを追加することによる最小の拡張。

しかし、あなたの答えに関係なく、Cからほとんど独占的に学べることは確かにいくつかあります(そしておそらく他のいくつかの言語)。

  • Cは歴史的に重要です。私たちがどこから来たのかを見て理解することができ、おそらく私たちがどこに行くのかについてもう少しコンテキストを得ることができるマイルストーンです。特定の制限が存在する理由を理解でき、特定の制限が解除されたことを理解できます。

  • Cは、安全でない環境で作業することを教えることができます。言い換えれば、言語(任意の言語)が何らかの理由であなたのためにそれを行うことができない、またはできないときにあなたの背中を見るように訓練することができます。これにより、安全な環境でも優れたプログラマを作成できます。自分でバグを減らすことができ、安全でないプログラムから余分な速度を絞るために一時的に安全をオフにできるからです(ポインタの使用など) C#では)、安全性にランタイムコストが伴う場合。

  • Cは、すべてのオブジェクトにストレージ要件、メモリレイアウト、有限のアドレス空間を介してメモリにアクセスできるという事実などがあることを教えることができます。他の言語ではこれらの問題に注意を払う必要はありませんが、いくつかのケースでは、より多くの情報に基づいた決定を下すのに役立ついくつかの直観があります。

  • Cは、ビルドシステムを通じて、リンケージおよびオブジェクトファイルの詳細やその他の複雑さについて学習できます。これにより、ネイティブにコンパイルされたプログラムがソースコードから実行までにどのように行われるかについて、実践的な理解を深めることができます。

  • Cは、未定義の振る舞いの概念を通して、新しい方法で考えるように心を曲げることができます。未定義の動作は、ソフトウェア開発における私のお気に入りの概念の1つです。非古典的なコンパイラに対する影響の研究は、他の言語では得られないユニークなメンタルエクササイズだからです。ただし、この側面を十分に理解するには、試行錯誤を拒否し、慎重かつ慎重に言語の学習を開始する必要があります。

  • しかし、おそらくCが小さな言語であるためにあなたに与えることができる最も重要な実現は、すべてのプログラミングがデータと操作に要約されるという考えです。階層と仮想ディスパッチを備えたインターフェイスを備えたモジュールクラス、または純粋な数学関数を使用して操作されるエレガントで不変の値として、物事を見ることができます。そしてそれはすべて大丈夫です-しかし、Cはそれがすべて単なるデータ+操作であることを思い出させます。精神的な障壁をかなり減らすことができるので、これは便利な考え方です。


5

Cが学習に適しているのは、Cが原則を教えているからではありません。それは物事がどのように、あなたを教えて働きます

Cは、運転するために建てられた70年代または80年代の古き良き自動車の1つと比較できます。それらを引き裂き、ねじごとにねじって、各部分がどのように機能するか、そしてそれがあなたの手で見ることができる他の部分とどのように連携するかを理解することができます。すべての部分を理解すると、全体がどのように機能するかを非常に明確に把握できます。

現代の言語は、エンジンが基本的にブラックボックスである現代の自動車に似ており、平均的な自動車の所有者には理解できないほど複雑です。これらの車は、多くのことを実行できます。最近では、自力で運転することを積極的に学習しています。そして、その複雑さと快適さにより、ユーザーインターフェイスは、エンジンで実際に行われているものからはるかに離れています。

Cでプログラミングを学ぶと、コンピューターを構成する多くのネジやナットに触れることになります。これにより、マシン自体の理解を深めることができます。たとえば、次のような長い文字列を作成するのが得策ではない理由を理解できます。

java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
     result = result + components[i];
};

(これは正しいJavaであり、しばらく使用していません...)しかし、そうであり、連結する数百万の小さなコンポーネントがある場合に、このコードが完全に停止する理由です。経験豊富なCプログラマーは、問題がどこにあるかを即座に知っており、そもそもそのようなコードを書くことを避けるでしょう。


私は完全に同意します。Cは物事の仕組みについて多くを教えてくれます。これは、a)高級言語が書かれた理由(例:抽象化する意味)、b)高級言語が舞台裏で機能する仕組み、確かな知識が必要です。それは原則を教えませんし、それほど簡単ではないかもしれませんが、あなたはそれ、コンピューター、そして結果としてより高いレベルの言語のより深い理解に敬意を払うでしょう。また、Joel SpolskyによるBack to Basicを読んでください:joelonsoftware.com/articles/fog0000000319.html
jleach

1
あなたの答えは確かに大丈夫ですがfor(int i = 0; i < strlen(s); i++)、Cで書くと、ループも2次の複雑さを持ち、Javaの例と同じくらい明白です;
Doc Brown

確かではありませんが、これを最適化するためにJavaコンパイラを信頼します:
ブルーノシェーパー

経験豊富なJavaプログラマーは、問題がどこにあるかを即座に把握しており、そもそもそのようなコードを書くことを避けるでしょう。この特定の問題は、基本的なJavaチュートリアルで説明されています。したがって、これは確かにCから学ぶことはできてもJavaから学ぶことはできません。
ピーターテイラー

@PeterTaylor Cを知っているJavaインストラクターがいるなら、はい。しかし、Cを知っている人々が死んでしまえば、この種の知識が残るとは思えません。Cプログラマーにとって、それはCストリングの定義そのものであり、私のコード例は効率的ではないことを伝えています。Javaプログラマーにとっては、使用する抽象化についての深い、難解で、ほとんど使用されていない知識であり、この種のコードを避けるように指示しています。さて、ここで少し誇張しますが、アイデアは得られます。Cプログラマーはそれを知っている必要があり、Javaプログラマーはそれを知らないで逃げることができます。
cmaster-モニカを

2

「プログラミングの背後にある原則」、特に理論的原則を学ぶにはCよりも優れた言語がありますが、Cは工芸について実用的で重要なことを学ぶのに良いかもしれません。greyfadeの答えは確かに正しいですが、私見では、自分でメモリを管理する方法よりもCから学ぶことができます。例えば、

  • 例外がない場合に完全なエラー処理を行うプログラムを作成する方法

  • オブジェクト指向の言語サポートなしでプログラムに構造を作成する方法

  • 動的なサイズ変更可能なリスト、辞書、または有用な文字列抽象化などのデータ構造がない場合のデータの処理方法

  • コンパイラーまたはランタイム環境が自動的に警告しない場合でも、配列オーバーフローなどの一般的なエラーを回避する方法

  • テンプレートまたはジェネリックの言語サポートなしでジェネリックソリューションを作成する方法

  • もちろん、自分で記憶を管理する方法を学ぶことができると言いましたか?;-)

さらに、Cを学習することにより、C ++、Java、C#、Objective Cの構文上の共通点がどこから来たのかを学習します。

2005年、Joel Spolskyは他の高レベル言語よりも先にCを学習すること推奨しています。彼の議論は

  • 「高レベルの言語で効率的なコードを作成することはできません。」

  • 「コンパイラやオペレーティングシステムで作業することはできません。これらは、最高のプログラミングジョブの1つです。」

  • 「大規模なプロジェクトのアーキテクチャを作成することは決して信頼できません」

  • while(*s++ = *t++);文字列をコピーする理由を説明できない場合、またはそれが世界で最も自然なことではない場合は、迷信に基づいてプログラミングしています

もちろん、彼が書いたことは確かに議論の余地がありますが、彼の議論の多くは今日でも有効です。


1
Cは、「Cがサポートしていないと思う高レベルのもの」を学ぶ前に学ぶのに非常に良い言語です。Cが実際にどのように機能するか(およびそれらがどれだけ高価か)を理解するのに役立つからです。
ブレンダン

@ブレンダン:あなたのコメントの意図が同意、意見の不一致、または私の答えに対する単なる副次的表現であるかどうかはわかりません。
Doc Brown

専門家によって書かれたCプログラムは、バッファオーバーランとハードクラッシュでリリースされます。したがって、規律のあるプログラマーはこれらのことを学ぶことを選択するかもしれませんが、C言語は本質的に単に貧しいというだけでは教えません。たとえば、例外なしでエラー処理を行い、オブジェクトのない構造を作成するための多くの悪い方法(さらに悪いことに、複数の一貫性のない方法を混在させる)があります。
エリックエイド

@ErikEidt:確かに、しかし特にCエコ圏では、これらのトピックを扱う本、チュートリアル、その他の資料がたくさんあります。たとえば、Steve Maguireの「Writing Solid Code」。もちろん、言語構文を学習するためにK&Rの初版を選んだとしても、おそらく彼はより優れたプログラマーになることはないでしょう。
Doc Brown

1

コンピューティングの2つの基本的な抽象概念は、チューリングマシンとラムダ計算です。Cは、チューリングマシンの計算ビューを試すための方法です。ただし、Cには独自の計算モデルが付属していることに注意してください。したがって、Cを学習すると、実際のアーキテクチャとはまったく異なるC抽象マシンの低レベルの詳細がわかります。Cで最初に教えられたことの1つは、「賢い」トリックを適用することでコンパイラーの裏をかこうとしないことでした。他の高水準言語と同様に、Cで記述すると、コンパイラーは抽象的なCマシンで何をするかを理解し、実際のハードウェアでそれを実現します。

つまり、Cを学習することで、ハードウェアで実際に何が起こるかを必ずしも把握できるとは限りません。「Cはマシンに近い」は「ほとんどの高レベル言語よりも近い」と理解されるべきです。「どのように機能するか」のより正確な図が必要な場合、ソフトウェアアーキテクチャを直接学習することは、よりやりがいのあることです。

一方、Cを学習すると、システムプログラミング、低レベルの型、ポインター、特にメモリの割り当てに慣れることができます。学習アルゴリズムとデータ構造に関しては、他の言語ではなくCで学習する利点はありません。


1
それでは、Cは高レベルの言語ではできないことをあなた
フィリップケンドール

2
暗黙の答えは「何も、少なくとも支持者が通常主張するものではない」だと思います。とにかく答えを理解する方法です。
ヨルグWミットタグ

-3

それは非常に開かれた質問であり、決定的な答えは得られないかもしれません。言語フレームワークの内部を理解すれば、すべての言語でほとんどすべてを学ぶことができます。Cは主にオペレーティングシステムを作成するために設計されているため、詳細を理解しなくてはなりません。長い年月を経ても、主に組み込みシステムとオープンソースプロジェクトのおかげで、依然として最も使用されている言語の1つです。だから、質問はあなたが何を学びたいのですか?そして、どのドメインで?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.