ずっと昔、K&R の ANSI 以前の時代には、関数は現在とはかなり異なって見えました。
add_numbers(x, y)
{
return x + y;
}
int ansi_add_numbers(int x, int y); // modern, ANSI C
のような関数を呼び出す場合add_numbers
、呼び出し規則に重要な違いがあります。関数が呼び出されると、すべての型が「昇格」されます。したがって、これを行う場合:
// no prototype for add_numbers
short x = 3;
short y = 5;
short z = add_numbers(x, y);
がx
に昇格されint
、y
が に昇格されint
、戻り値の型がデフォルトであると想定さint
れます。同様に、a を渡すfloat
と double に昇格されます。これらの規則により、適切な戻り値の型を取得し、適切な数と型の引数を渡す限り、プロトタイプは不要であることが保証されました。
プロトタイプの構文は異なることに注意してください:
// K&R style function
// number of parameters is UNKNOWN, but fixed
// return type is known (int is default)
add_numbers();
// ANSI style function
// number of parameters is known, types are fixed
// return type is known
int ansi_add_numbers(int x, int y);
昔の一般的な方法は、ほとんどの部分でヘッダー ファイルを使用せず、プロトタイプをコードに直接貼り付けることでした。
void *malloc();
char *buf = malloc(1024);
if (!buf) abort();
最近の C では、ヘッダー ファイルは必要悪として受け入れられていますが、最新の C の派生物 (Java、C# など) がヘッダー ファイルを削除したように、昔の人もヘッダー ファイルの使用をあまり好みませんでした。
型安全性
C以前の古い時代について私が理解していることから、静的型付けシステムが常に多くあるとは限りませんでした。int
ポインターを含め、すべてが でした。この古い言語では、関数プロトタイプの唯一のポイントは、アリティ エラーをキャッチすることでした。
したがって、最初に関数が言語に追加され、次に静的型システムが後で追加されたと仮定すると、この理論はプロトタイプがオプションである理由を説明します。この理論は、配列が関数の引数として使用されたときにポインターに崩壊する理由も説明しています。これは、このプロト C では、配列は、スタック上のスペースを指すように自動的に初期化されるポインターに過ぎなかったからです。たとえば、次のようなことが可能だった可能性があります。
function()
{
auto x[7];
x += 1;
}
引用
タイプレスについて:
両方の言語 [B と BCPL] は型がないか、固定長のビット パターンである「単語」または「セル」という単一のデータ型を持っています。
整数とポインタの等価性について:
したがって、p
が別のセルのインデックス (またはアドレス、またはポインタ) を含むセル*p
である場合は、式の値または代入のターゲットとして、ポイント先のセルの内容を参照します。
サイズの制約のためにプロトタイプが省略されたという理論の証拠:
開発中、彼はメモリの制限と格闘し続けました。言語を追加するたびにコンパイラが膨張し、ほとんど収まりませんでしたが、機能を利用して書き直すたびにサイズが小さくなりました。