Cコンパイラがそれほど少ないのはなぜですか?


72

Cは、世界で最も広く使用されている言語の1つです。既存のコードの大部分を占め、膨大な量の新しいコードに引き続き使用されます。ユーザーに愛されており、非常に広く移植されているため、Cを実行できることはプラットフォームの非公式な定義の多くに当てはまります。

それでは、すべてのコンパイラはどこにありますか?

デスクトップには、(現実的に)GCCとClangの2つがあります。数秒間考えてみれば、おそらくインテルも存在していることを覚えているでしょう。他の人はほんの一握りで、平均的な人が名前を付けるにはあまりにもあいまいで、ほとんどの場合、最近の言語バージョン(またはよく定義された言語サブセット、単に「サブセット」)をサポートすることをほとんど気にしません。このリストのメンバーの半分は歴史的な脚注です。残りのほとんどは非常に特殊化されており、実際には完全な言語を実装していません。実際にオープンソースであると思われるものはほとんどありません。

SchemeとForth-ファンに愛されている他の小さな言語-はおそらく実際のユーザーよりも多くのコンパイラを持っています。SMLのようなものでも、Cよりも「深刻な」実装を選択できます。一方、検証を目的する新しい(未完成の)Cコンパイラの発表では実際にかなり否定的な応答が見られ、ベテランの実装は、 C99。

どうして?Cの実装はとても難しいですか?C ++ではありません。ユーザーは、それがどの複雑なグループに属するかについて非常に歪んだ考えを持っているだけですか(つまり、実際にはSchemeよりもC ++に近いということですか)。


61
MSVCは、少なくともC89コンパイラとして引き続きカウントされます。おそらくインテルよりも人気があります。
Rufflewind

22
ウィキペディアには、かなりの数のCコンパイラがリストされています。彼らが得る非常にあなたが埋め込まれた領域に自分自身を見つけるとき共通。

113
Cコードをコンパイルするには、いくつのコンパイラが必要ですか?
ブライアンチェン

76
質問は誤った前提に基づいています。アナログデバイス、armcc、ブルースのCコンパイラ、ベアCクロスコンパイラ、ボーランドコンパイラ、clangコンパイラ、Cosmic Cコンパイラ、CodeWarriorコンパイラ、doktoコンパイラ、エリクソンコンパイラ。まだアルファベットの最初の5文字。ありめちゃくちゃ大きな Cコンパイラの数が。問題は、「これらの数十を実際のCコンパイラとして数えないと、なぜCコンパイラがそれほど少ないのですか?」です。Cコンパイラの大部分はおもしろくないと定義したので、Cコンパイラはあまり多くありません。
エリックリッパー

19
「なぜ」の質問は、このサイトにとって最高の悪い質問であり、「なぜですか」質問はもっと悪いです。パーティーであなたに会って「だから、なぜヨットに乗ってみませんか?」あなたはそれが奇妙な質問であると正しく思うでしょう。技術的に困難で、肉体的にリスクがあり、非常に高価な趣味に従事しないことを正当化する必要はありません。些細でないソフトウェアを書くことは、費用がかかり、困難であり、リスクがあります。そのため、大きな動機付けが必要です。より良い質問は、「なぜそれほど多くのCコンパイラがあるのですか?」複数あることは驚くべきことです。
エリックリッパー

回答:


153

今日は、あなたがする実際のCコンパイラを必要とする最適化コンパイラ、特にCは、ハードウェアに近い言語は、もはやであるため、現在のためのプロセッサは(信じられないほど複雑なアウトオブオーダーパイプライン化スーパースカラ、複雑でキャッシュTLB、したがって、命令のスケジューリングなどが必要です)。現在のx86プロセッサは、両方が同じマシンコードを実行できる場合でも、前世紀のi386プロセッサとは異なります。Cは低レベルの言語ではない(お使いのコンピューターは高速なPDP-11ではない) David Chisnallによる論文をご覧ください。

tinyccnwccのような素朴な非最適化Cコンパイラを使用している人はほとんどいません。最適化コンパイラが提供するコードよりも数倍遅いコードを生成するためです。

最適化コンパイラのコーディングは困難です。GCCとClangの両方が、「ソース言語に依存しない」コード表現(GCCのGimple、ClangのLLVM)を最適化していることに注意してください。優れたCコンパイラの複雑さは、解析段階ではありません!

特に、C ++コンパイラを作成することは、Cコンパイラを作成することほど難しくありません:C ++を解析して内部コード表現に変換することは複雑です(C ++仕様が複雑なため)が、よく理解されていますが、最適化の部分はさらに複雑です複雑(GCCの内部:ミドルエンド最適化、ソース言語およびターゲットプロセッサニュートラルがコンパイラの大部分を構成し、残りは複数の言語のフロントエンドと複数のプロセッサのバックエンドでバランスが取れています)。したがって、ほとんどの最適化Cコンパイラは、C ++、Fortran、Dなどの他の言語もコンパイルできます。GCCのC ++固有の部分は、コンパイラの約20%です。

また、C(またはC ++)は非常に広く使用されているため、言語のセマンティクスを十分に正確に定義していない公式の標準に正確に準拠していない場合でも、コードがコンパイル可能であると人々は期待しています(したがって、各コンパイラーは独自の解釈を持つことができます)それの)。CompCertで実証されたCコンパイラーとFrama -C静的アナライザーも調べてください。これらは、Cのより正式なセマンティクスに注意を払っています。

そして、最適化はロングテールの現象です。いくつかの簡単な最適化を実装するのは簡単ですが、コンパイラの競争力を高めることはありません!多くの異なる最適化を実装し、それらを巧みに編成および結合して、競争力のある実際のコンパイラを取得する必要があります。つまり、実際の最適化コンパイラは複雑なソフトウェアでなければなりません。ところで、GCCとClang / LLVMの両方には、いくつかの内部に特化したC / C ++コードジェネレーターがあります。そして、両方とも巨大な獣(毎年数パーセントの成長率を持つ数百万のソースコード行)であり、大規模な開発者コミュニティ(数百人、ほとんどがフルタイム、または少なくともハーフタイム)を持っています。

コンパイラの一部が並行して実行できたとしても(私の知る限り)、マルチスレッドCコンパイラはありません(プロシージャ内最適化、レジスタ割り当て、命令スケジューリングなど)。また、(特にLTOを使用した)並列ビルドでは必ずしも十分ではありません。make -j

また、Cコンパイラをゼロからコーディングするための資金を得るのは難しく、そのような努力は数年続く必要があります。最後に、ほとんどのCまたはC ++コンパイラは今日のフリーソフトウェアです(スタートアップが販売する新しいプロプライエタリコンパイラの市場はもはやありません)、または少なくとも独占的な商品(Microsoft Visual C ++など)であり、コンパイラにはフリーソフトウェアであることがほぼ必要です(多くの異なる組織からの貢献が必要だからです)。

フリーのソフトウェアとしてCコンパイラをゼロから開発するための資金を得ることができればうれしいですが、それが今日可能であると信じるほど素朴ではありません!


14
(there is no more a market for proprietary compilersVisual Studioチームにそれを教えてください...
メイソンウィーラー

18
マイクロソフトには独占権があります。私は、新しいCコンパイラを開発している小さな会社がそれらの多くを売らないことを意味しました。MSVCの最近の独占的な競合他社に名前を付けることはできますか?
バジルスタリンケビッチ

12
HPCの世界には多くの独自のコンパイラがあります。PGCC、NAG、およびICCが最も広く使用されています。
-Davidmh

37
@MasonWheeler:VSは最近(ビールのように)無料で配布されています。非フリーバージョンはツールを追加しますが、VS2013のCコンパイラはすべてのバージョンで同じです。市場はありません。彼らにとってもそうです。
–MSalters

3
しかし、GCCとLLVMはどちらもはるかに低い表現で動作しており、同様にC ++とC(GCCの場合はAdaとFortran)コードを最適化します。私は反対に、C ++はCよりも多くの最適化を必要とします(特にSTLを使用してコードをコンパイルする場合)。
バジルスタリンケビッチ

70

Cの実装はごく少数であるという根本的な仮定に異議を唱えたいと思います。

私もCを知らず、Cを使用せず、Cコミュニティのメンバーでもありませんが、あなたが言及した少数のコンパイラよりもはるかに多くを知っています。

何よりもまず、おそらくデスクトップ上のGCCとClangの両方を完全にd小化するコンパイラがあります。MicrosoftVisualC。離れた旧従来のデスクトップユーザーから、Windowsはまだ支配的なデスクトップOS、およびWindowsデスクトップのCプログラムの大半は、おそらく、Microsoftのツールを使用してコンパイルされています。

従来、すべてのOSベンダーとすべてのチップベンダーには、独自のコンパイラがありました。Microsoftは、OSベンダーとしてMicrosoft Visual Cを持っています。IBMは、OSベンダーとチップベンダーの両方として、XLC(AIXのデフォルトシステムコンパイラであり、AIXとi / OSの両方をコンパイルするコンパイラ)を持っています。Intelには独自のコンパイラがあります。Sun / Oracleには、Sun Studioに独自のコンパイラがあります。

次に、PathScaleやThe Portland Groupなどの高性能コンパイラベンダーがあります。これらのコンパイラ(およびOpenMPライブラリ)は、数値演算に使用されます。

デジタルマーズもまだビジネスにあります。Walter Brightには、地球上で(ほとんど)自分でプロダクション品質のC ++コンパイラを作成した唯一の人物であるというユニークな区別があると思います。

最後になりましたが、組み込みマイクロコントローラー用の独自のコンパイラーがすべて揃っています。IIRCでは、コンピューティングの歴史全体でデスクトップ、モバイル、サーバー、ワークステーション、およびメインフレームのCPUが販売されているよりも、毎年多くのマイクロコントローラーが販売されています。したがって、これらは決してニッチ製品ではありませ

名誉言及はに外に出るTruffleC、Cのインタプリタ(!)JVM上で実行されている(!)を越え(任意の特定のベンチマークで最速の方)GCCとクランよりもわずか7%遅いトリュフASTインタプリタのフレームワークを使って書かれましたコンピュータ言語のベンチマークゲームであり、マイクロベンチマークの両方よりも高速です。TruffleCを使用して、Truffleチームは、JRuby + Truffleのバージョンを取得して、実際のC Ruby実装よりも速くRuby C拡張を実行することができました!

だから、これらはあなたがリストしたものに加えて6つの実装であり、Cについて何も知らなくても頭の中で名前を付けることができます。


1
Microsoft Visual C以外では、言及しているCコンパイラのほとんどはめったに使用されません。
バジルスタリンケビッチ

6
MSVCは大きなC ++コンパイラですが、Cの場合は使用が難しく、C89で永続的にスタックします。マイクロコントローラーのコンパイラーは通常、ターゲット固有であり、C89でスタックし、風変わりです。TruffleCはまだ利用できないようです(しかし、興味深いです、ありがとう)。PathscaleとDigital Marsは、私が探していた反例のようなものに見えます。
ルーシェンコ

8
@Mario私の意味は、C89が壊れているということではありませんが、C89は言語の最新の形式ではありません。そしてそれは、最新のコンパイラ少ないことを意味します。
ルーシェンコ

6
@Leushenko MSVCはC89で永続的にスタックしません。いくつかの議論があり、さらにC99機能を追加する必要があります。まず最初に、C99ライブラリのほとんどはMSVC 2015以降でサポートされており、いくつかの言語機能もサポートされています(主にC ++ 11に必要なもの)。
モーウェン

5
@Morwenn:Microsoftのポリシーでは、C99はC ++がまだ解決していない問題を解決せず、システムプログラミングを行う場合は、CのようなC ++のサブセット(ランタイムやコンパイラがどこに置くかを制御できない場所-ページングが無効になっている状態からコードまたはデータがページアウトされないようにする必要がある場合に重要です)。C99の唯一の機能は、後のC ++仕様で必要なものと、実装するのが簡単なものです。
マイクディミック

8

コンパイラーはいくつ必要ですか?

異なる機能セットがある場合、移植性の問題が発生します。商品化されている場合は、「デフォルト」(GCC、Clang、またはVS)のいずれかを選択します。最後の5%のパフォーマンスに関心がある場合は、ベンチマークオフがあります。

レクリエーションや研究目的でプログラミング言語の仕事をしている場合は、より現代的な言語である可能性があります。したがって、SchemeおよびML用のおもちゃコンパイラの急増。OCamlは、玩具ではなく、アカデミック以外の用途でも牽引力を得ているようです。

これは言語によって大きく異なることに注意してください。Javaには、基本的にSun / OracleツールチェーンとGNUツールチェーンがあります。Pythonにはさまざまなコンパイラがあり、標準のインタプリタと比べてどれも本当に尊重されていません。RustとGoにはそれぞれ1つの実装があります。C#にはMicrosoftとMonoがあります。


1
MLコンパイラを開発するより興味深い理由があることは明らかです...私は、Cコミュニティがおそらく3桁大きいと、その効果を相殺すると考えました。しかし、あなたは正しいかもしれません、1000 * 0まだ0です。
ルーシェンコ

多くの場合、新しいコンパイラの作成は、コミュニティの断片化(リンクの原因または原因のいずれか)とリンクしています。たとえば、egcsとgccのメンテナーが分割されます。また、Cソースの互換性は100%未満になる傾向があります。
pjc50

@ pjc50:標準の記述方法は、基本タイプのようなものに基づいて、Cをいくつかのばらばらの方言に効果的に分割しint、同じソースコードを非常に異なる方法で解釈するために異なるコンパイラを必要とします。
supercat

5
Goには2つの実装(6g/ 8g/…ツールチェーンとgccgo)があります。erGoと呼ばれる非常に興味深い独自の商用実装もありました。これは、a)gccgoもオリジナルのGoコンパイラもWindowsでうまく機能しなかったGoのネイティブWindows実装でした。b)Goに賭けた会社1.0になる前、およびc)Goで記述されたGoの最初の実装(gccgoと6g / 8gは両方ともCで記述されています)。しかし、プロジェクトと会社の両方は、彼らがクローズドベータから抜け出す前に消えました。
ヨルグWミットタグ

6

C / C ++は、共通の仕様の3つの主要な実装を備えているという点で、コンパイルされた言語の中でも独特です。

あまり使用されないものはすべて却下するという規則に従って、コンパイルされた他のすべての言語には0〜1があります。

そして、「コンパイル済み」を指定する必要があるのはjavascriptだけだと思います。


2
ラベル「C」は、さまざまな言語に適用されます。コードuint16_t a=48000u; unsigned uint32_t b=(a*a)/2;b値8192に割り当てると定義するものもあります。1152000000を割り当てると定義するものもあります。ほとんどの場合、これを未定義の動作と見なし、3299483648を格納する可能性がありますが、その点で約束はしません。
-supercat

1
@supercat:ああ、オーバーフローと整数プロモーションルールを備えた非常に奇妙なものです。それは明らかに使用する2かどうかにかかってい2uます。
ザンリンクス

1
@ZanLynx:2対2uが正当に問題になるケースはないと思います。私がそれが重要であるかもしれないことを知っている唯一のケースは、2と2uの両方のUndefined Behaviorに関係しています。
supercat

3
@supercat:どのようにして未定義の動作を取得し/2uますか?符号なしオーバーフローは(実装定義のNのモジュロ2 ^ Nとして)定義されますが、除算はオーバーフローすることさえできません。
MSalters

2
未定義の動作は、signed intに昇格される値の乗算から発生しますが、その積はそのタイプに適合しません。その結果を符号なしintに強制すると、結果の値の解釈が変更される可能性がありますが、前の計算の未定義の動作は無効になりません。
supercat

5

では、ターゲット言語は何ですか?

SMLコンパイラは多くの場合、CまたはLLVMのようなもの(または、リンク、JVMまたはJavaScriptに見られる)をターゲットとしています。

Cをコンパイルしているのは、JVMに行くからではありません。あなたはCより悪いものに行くでしょう。はるかに悪い。そして、すべてのターゲットプラットフォームで、そのマイナーな地獄を何度も複製することになります。

確かに、CはC ++ではありませんが、SchemeよりもC ++に近いと言えます。それは未定義の振る舞いの悪の独自のサブセットを持っています(組み込み型のサイズを見ています)。そして、その特徴を台無しにした場合(または「正しく」予期せずにそれを行った場合)、あなたはあなたがどれほどひどいかを教えてくれる重要なシステム上に何十年もの既存のコードを持っています。SMLコンパイラを台無しにすると、動作しなくなります-誰か気づくかもしれません。いつか。


SML / NJとPolyMLの両方がマシンコードにコンパイルされています...
Basile Starynkevitch

2
intサイズ「未定義の動作」はどうですか?とにかくコンパイラーベンダーの負担になるのはなぜでしょうか?コンパイラ作成者にとっての唯一の本当の負担は、int幅が実装定義であり、不特定ではないため、何をしたかを文書化する必要があることです。
–MSalters

@MSalters実際には、確立されたプラットフォームのコンパイラ作成者には、以前に行った他のプロセスと一致する負担があります。これは文書化および標準化される場合もあれば、そうでない場合もあります。intのサイズを見つけるのは簡単ですが、レジスタ値で何が行われ、関数を呼び出すときに引数が保存される場所(関数の引数の型と戻り値の型によって変わる場合があります)、構造体レイアウトルール、など
-Random832

@MSaltersほとんどの人はint32ビットまたは64ビットを期待していますが、16ビットまで小さくすることができます。範囲外の数値を生成することはまったく難しくなく[−32767, +32767]intオーバーフローはUBです。ありますchar/ shortに昇格なっint たり unsigned intするかどうかに応じて、intさらにからの変換トリガすることができます元の型のすべての値を表すことができますintへのunsigned intオペランドが異なる種類を持っていたとは異なる変換しまった場合は、プラスあなたは結果を変数に割り当てる可能性の別の変換は、 。
ドーバル

@MSalters標準型のサイズには十分な余裕があり、暗黙的な変換が十分に行われているため、ほとんどすべての非自明なCプログラムには、間違った動作をしたり未定義の原因となる正当な整数サイズの選択肢があります動作。
ドーバル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.