まず、ここでは "C"についてのみ言及していますが、C ++にも同じことが当てはまることに注意してください。
ゲーデルに言及したコメントは部分的に(しかし部分的にのみ)論点でした。
簡単に言えば、C標準の未定義の動作は、標準が定義しようとしていることと定義していないことの境界を主に指摘しているだけです。
Godelの定理(2つあります)は、(独自のルールによって)完全で一貫性があることが証明できる数学的システムを定義することは基本的に不可能だと言っています。ルールを作成して完全なものにすることができます(彼が扱ったケースは自然数の「通常の」ルールでした)。そうでなければ、その一貫性を証明することができますが、両方を持つことはできません。
Cのようなものの場合、それは直接当てはまりません。ほとんどの場合、システムの完全性または一貫性の「証明可能性」は、ほとんどの言語設計者にとって高い優先順位ではありません。同時に、はい、おそらく「完全な」システム、つまり完全で一貫性のあるシステムを定義することは不可能であることを知っていることによって、少なくともある程度影響を受けました。そのようなことが不可能であることを知ることは、一歩後退し、少し呼吸し、彼らが定義しようとするものの境界を決定するのを少し簡単にしたかもしれません。
(まだ)慢であると非難される危険性があるので、私はC標準を(部分的に)2つの基本的な考え方に支配されていると特徴付けます。
- この言語は、可能な限りさまざまなハードウェアをサポートする必要があります(理想的には、すべての「健全な」ハードウェアを妥当な下限までサポートする必要があります)。
- この言語は、指定された環境で可能な限り多種多様なソフトウェアの作成をサポートする必要があります。
最初の意味は、誰かが新しいCPUを定義する場合、設計が少なくともいくつかの単純なガイドラインに合理的に近い限り、そのために、Cの適切で堅実な使用可能な実装を提供できることを意味します-基本的に、 Von Neumannモデルの一般的な順序に従っており、少なくともある程度の合理的な最小メモリ量を提供します。これは、C実装を可能にするのに十分なはずです。「ホストされた」実装(OS上で実行される実装)の場合、ファイルにかなり密接に対応する概念をサポートする必要があり、特定の最小文字セット(91が必要)を持つ文字セットが必要です。
第二は、ハードウェアを直接操作するコードを記述することができなければならないことを意味し、その最終的にありますが、ブートローダー、オペレーティング・システム、など任意のOSなしで実行組み込みソフトウェア、のようなものを書くことができ、いくつかのこの点で限界が、そのほぼすべて実用的なオペレーティングシステム、ブートローダーなどには、アセンブリ言語で記述されたコードが少なくとも少し含まれている可能性があります。同様に、小さな組み込みシステムでも、ホストシステム上のデバイスへのアクセスを許可するために、少なくとも何らかの種類の事前に作成されたライブラリルーチンが含まれている可能性があります。正確な境界を定義することは困難ですが、そのようなコードへの依存を最小限に抑えることを目的としています。
言語での未定義の動作は、主に言語がこれらの機能をサポートするという意図によって決まります。たとえば、この言語を使用すると、任意の整数をポインターに変換し、そのアドレスにあるものにアクセスできます。この規格は、あなたが何をしたときに何が起こるかを言おうとはしません(例えば、いくつかのアドレスからの読み取りでさえ、外部から見える影響を与えることができます)。同時に、それはあなたがそのようなことをすることを妨げることを試みません。なぜなら、あなたはCで書くことができるはずのある種のソフトウェアのために必要だからです。
他の設計要素によって駆動される未定義の動作もあります。たとえば、Cのもう1つの目的は、個別のコンパイルをサポートすることです。これは、たとえば、ほとんどの人が通常のリンカーモデルとして見ているものにほぼ従うリンカーを使用して、ピースを「リンク」できることを意味します。特に、言語のセマンティクスを知らなくても、別々にコンパイルされたモジュールを完全なプログラムに結合することが可能であるべきです。
別のタイプの未定義の動作(CよりもC ++で一般的です)があります。これは、単にコンパイラテクノロジの制限のために存在します。基本的にエラーであり、おそらくコンパイラがエラーとして診断することを知っていること、しかし、コンパイラテクノロジの現在の制限を考えると、すべての状況で診断できるかどうかは疑わしいです。これらの多くは、個別のコンパイルなどのその他の要件によって駆動されるため、主に競合する要件のバランスをとることが問題となります。考えられるすべての問題が診断されるように機能を制限するのではありません。
これらの意図の違いは、CとJavaやMicrosoftのCLIベースのシステムのようなものとの違いのほとんどを促進します。後者は、はるかに限られたハードウェアセットでの作業、またはターゲットとするより具体的なハードウェアをエミュレートするためのソフトウェアを必要とすることに明確に制限されています。また、ハードウェアの直接的な操作を防止することも意図しており、その代わりに、JNIやP / Invoke(およびCのようなコードで記述されたコード)を使用してそのような試みを行う必要があります。
ゴデルの定理に少し戻って、似たようなものを描くことができます。JavaとCLIは「内部的に一貫した」代替案を選択し、Cは「完全な」代替案を選択しました。もちろん、これは非常に大まかな例えです。どちらの場合でも、誰かが内部の一貫性または完全性のいずれかの正式な証明を試みているとは思いません。それにもかかわらず、一般的な概念は、彼らが取った選択にかなり密接に適合します。