質問

ANSI C に関するウィキペディアの記事 言います:

ANSI C 標準化プロセスの目的の 1 つは、その後導入された非公式の機能の多くを組み込んだ、K&R C (最初に公開された標準) のスーパーセットを作成することでした。ただし、標準委員会には、(C++ プログラミング言語から借用した) 関数プロトタイプや、より高性能なプリプロセッサなど、いくつかの新機能も含まれています。パラメーター宣言の構文も、C++ スタイルを反映するように変更されました。

そうなると、違いがあるのではないかと思います。ただし、K&R C と ANSI C の比較は見つかりませんでした。そのような文書はありますか?そうでない場合、主な違いは何ですか?

編集:K&R の本の表紙には「ANSI C」と書かれていると思います。少なくとも私が家にあるバージョンはそうだと思います。ということは、もう違いはないのでしょうか?

役に立ちましたか?

解決

ここで「K&R C」とは何かについて混乱があるかもしれません。この用語は、「Cプログラミング言語」の初版で文書化されている言語を指します。大ざっぱに言えば:1978 年頃の Bell Labs C コンパイラの入力言語。

カーニハンとリッチーは、ANSI 標準化プロセスに関与しました。「ANSI C」方言は「K&R C」に取って代わり、「The C Programming Language」のその後の版では ANSI 規約が採用されています。「K&R C」は、一部のコンパイラが依然としてレガシー コードを受け入れる場合を除いて、「死んだ言語」です。

他のヒント

関数プロトタイプは、K&R C と C89 の間で最も明白な変更でしたが、他にもたくさんありました。C ライブラリの標準化にも多くの重要な作業が行われました。標準 C ライブラリは既存の実践を成文化したものでしたが、 複数 既存の慣行がそれをさらに困難にしていました。P.J.プラウガーの本、 標準 C ライブラリ, は非常に参考になるもので、舞台裏の詳細についても説明しています。 なぜ 図書館は結局そのようになりました。

ANSI/ISO 標準 C は、ほとんどの点で K&R C と非常に似ています。ほとんどの既存の C コードは、多くの変更を加えずに ANSI コンパイラ上に構築することが意図されていました。ただし、重要なのは、標準化以前の時代には、言語のセマンティクスが各コンパイラー ベンダーによって解釈可能であったことです。ANSI C は、すべてのコンパイラを同等の立場に置く言語セマンティクスの共通の記述を導入しました。20 年ほど経った今では当たり前のことだと思われがちですが、これは大きな成果でした。

ほとんどの場合、保守すべき標準以前の C コードベースがない場合は、それについて心配する必要がないことを嬉しく思うはずです。もしそうするなら、あるいはさらに悪いことに、古いプログラムをより現代的な基準に引き上げようとしているなら、私も同情します。

いくつかの小さな違いはありますが、K&R の後のバージョンは ANSI C 用であると思いますので、実質的な違いはもうありません。
「C Classic」では、より適切な用語がなかったため、関数を定義する方法が少し異なりました。

int f( p, q, r )  
int p, float q, double r;  
{  
    // Code goes here  
}

もう一つの違いは関数プロトタイプだったと思います。プロトタイプは引数や型のリストを受け取る必要はありませんでした。実際、受け取ることはできませんでした。ANSI C ではそうなります。

  1. 関数のプロトタイプ。
  2. 定数修飾子と揮発性修飾子。
  3. ワイド文字のサポートと国際化。
  4. 逆参照せずに関数ポインタを使用できるようにします。

もう 1 つの違いは、関数の戻り値の型とパラメーターの型を定義する必要がないことです。これらは int であるとみなされます。

f(x)
{
    return x + 1;
}

そして

int f(x)
int x;
{
    return x + 1;
}

は同一です。

  • 関数プロトタイピング:ANSI C は C++ 関数プロトタイプ手法を採用しており、関数の定義と宣言には関数名、引数、データ型、戻り値のデータ型が含まれます。関数プロトタイプにより、ANSI c コンパイラーは無効な数の引数を渡すユーザー プログラム内の関数呼び出しをチェックできます。これらは、K&R C コンパイラの主要な弱点を修正します。ユーザー プログラム内の無効な呼び出しは、コンパイルには合格しますが、実行時にプログラムがクラッシュすることがよくあります。

違いは次のとおりです。

  1. プロトタイプ
  2. ワイド文字のサポートと国際化
  3. const キーワードと volatile キーワードのサポート
  4. 関数ポインタを逆参照として使用できるようにする

ANSI C と K&R C の主な違いは次のとおりです。

  • 関数のプロトタイピング
  • const および volatile データ型修飾子のサポート
  • ワイド文字と国際化をサポート
  • 逆参照せずに関数ポインタを使用できるようにする

ANSI C は C++ 関数プロトタイプ手法を採用しており、関数の定義と宣言には関数名、引数のデータ型、戻り値のデータ型が含まれます。関数プロトタイプを使用すると、ANSI C コンパイラーは、無効な数の引数または互換性のない引数データ型を渡すユーザー プログラム内の関数呼び出しをチェックできます。これらは、K&R C コンパイラの主要な弱点を修正します。

例:to は関数 foo を宣言し、foo が 2 つの引数を取る必要があります

 unsigned long foo (char* fmt, double data)
 {
      /*body of foo */
 }

最大の違いは、関数のプロトタイピングと関数の引数の型を記述する構文だと思います。

まだ誰も言及していない大きな違いは、ANSI 以前は、C は仕様ではなく先例によって主に定義されていたことです。特定の操作が一部のプラットフォームでは予測可能な結果を​​もたらすが、他のプラットフォームではそうではない場合。2 つの無関係なポインターに関係演算子を使用するなど)、前例により、プログラマーがプラットフォーム保証を利用できるようにすることが強く支持されました。例えば:

  1. すべてのオブジェクトへのすべてのポインター間の自然なランキングを定義するプラットフォームでは、任意のポインターへの関係演算子の適用に依存してそのランキングが得られる可能性があります。

  2. あるポインタが別のポインタよりも「大きい」かどうかをテストする自然な手段が、真か偽の値を生成すること以外にいかなる副作用も持たないプラットフォームでは、任意のポインタへの関係演算子の適用も同様に、いかなる側面も持たないことに依存する可能性があります。 - true または false の値を生成する以外の効果。

  3. 2 つ以上の整数型が同じサイズと表現を共有するプラットフォームでは、そのような整数型へのポインターを利用して、同じ表現を持つ他の型の情報を読み書きすることができます。

  4. 整数オーバーフローが自然にサイレントにラップされる 2 の補数プラットフォームでは、「int」より小さい符号なしの値を含む演算は、結果が INT_MAX+1u と UINT_MAX の間にある場合に、その値が符号なしであるかのように動作することに依存する可能性があります。より大きな型に昇格されず、左オペランドとしても使用されませんでした。 >>, 、どちらのオペランドも /, %, 、または任意の比較演算子。 ちなみに、標準の理論的根拠では、小さな符号なし型が符号付き型に移行する理由の 1 つとしてこれが挙げられています。.

C89 より前は、上記の前提が自然には当てはまらないプラットフォーム用のコンパイラが、どの程度の長さの前提を維持することが期待されるのかは不明でしたが、そのような前提を簡単かつ低コストで維持できるプラットフォーム用のコンパイラが存在することはほとんど疑いの余地がありませんでした。そうすべきです。C89 標準の作成者は、次の理由からわざわざそれを明言しませんでした。

  1. ライターが意図的に鈍感になっていないコンパイラは、現実的な場合は何も言われなくてもそのようなことをやり続けるでしょう (小さな符号なしの値を符号付きに促進するという理論的根拠は、この考えを強く補強します)。

  2. 標準では、スタック オーバーフローを発生させずに、おそらく人為的に作られた 1 つのプログラムを実行できる実装のみを要求し、鈍感な実装は他のプログラムを未定義動作を呼び出すものとして扱うことができるが、鈍感なコンパイラ作成者の書き込みについて心配する価値はないと考えていました。 「適合」していても役に立たない実装。

「C89」は当時、「C89 によって定義された言語に、プラットフォームが提供するあらゆる追加機能と保証を加えたもの」を意味すると解釈されていましたが、gcc の作成者は、C89 で義務付けられたものを超える機能や保証を除外する解釈を推し進めてきました。

英国に対するあらゆる主張にもかかわらず、K&R は、ハードウェアに至るまで、あらゆる種類の機能を提供できる能力を持っています。今の問題は、K&R C の数百万行を、何もいじらずにクリーンにコンパイルできるコンパイラ (できれば無料) を見つけることです。また、AMD マルチコア プロセッサなどで実行できます。

私が知る限り、GCC 4.x.x シリーズのソースを調べたところ、私が準備している以上の努力をせずに、-traditional および -cpp-traditional ラグ機能を以前の動作状態に再アクティブ化する簡単なハックはありません。入れます。また、K&R pre-ansi コンパイラーを最初から構築する方が簡単です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top