3

K&Rを通してプログラミングを学んでいます。ここまでは順調ですが、セクション 1.8 (関数) のコード行の役割については不明です。

セクション 1.8 で、著者はある整数を別の整数で累乗する関数を作成する方法を示します。

本に書かれていたので、以下にコードを貼り付けました。すべて正常に出力されます。しかし、なぜ彼らがこの行を一番上に含めたのかわかりません:

int power(int m, int n);

この本では、プログラムが整数 m を n 乗すると述べていることを除けば、それについては触れていません。コードから行を削除しても、プログラムは正常に出力されます。

これを正しく理解していれば、行

int power(int base, int n)

関数を作成し、その下の中括弧で関数を定義します。次に、main の下の中かっこが関数を呼び出してチャートを出力します。

だから、それはすべて理にかなっているようです。しかし、一番上の行が何をするのかわかりません。

無関係かもしれませんが、何かが欠けている可能性がはるかに高いようです。なぜその行があるのか​​、誰かが私に教えてくれますか?

#include <stdio.h>

int power(int m, int n);

/* test power function */
main()
{
int i;

    for (i = 0; i < 10; ++i)
        printf("%d %d %d\n", i, power(2,i), power(-3, i));
    return 0;
}

/* power: raise base to n-th power; n >= 0 */

int power(int base, int n)
{
    int i, p;

    p = 1;
    for (i = 1; i <= n; ++i)
        p = p * base;
    return p;
}
4

6 に答える 6

7

最初の行は関数の宣言です。下部のコード ブロックは、関数の定義です。

ISO C 標準の 1999 年版以降、目に見える宣言なしで関数を呼び出すことは違法 (制約違反) です。宣言は呼び出しの前に行う必要があります。

このような単純なプログラムの場合、 (定義は宣言も提供するため)power()の定義の前にの完全な定義を記述できますmain()が、より複雑なケース (再帰呼び出しなど) では、別の宣言を提供する必要があることがよくあります。

大規模なプログラムの場合、すべての関数宣言をヘッダー ファイル (foo.hなど) にまとめ、対応する定義をソース ファイル ( など) にまとめるのが一般的foo.cです。#include "foo.h"ディレクティブは、宣言を他のファイルで可視にするために使用されます。本書の後半で、そのようなことがわかります。

(K&R2 がカバーする 1990 年以前のバージョンの C では、目に見える宣言なしで関数を呼び出すことができる場合がありますが、とにかく明示的な宣言を提供することは依然として非常に良い考えです。)

ちなみに、メインプログラムの宣言は、int main(void)単にmain().

用語: 「プロトタイプ」は、パラメーターの型を指定する関数宣言です。

int power(int base, int n);    /* a declaration that's also a prototype */
int power(int, int);           /* likewise */
int power();                   /* a declaration but not a prototype */

(パラメータ名は定義では必須ですが、スタンドアロン宣言ではオプションです。)

特殊なケースとして、パラメータのない関数のプロトタイプは を使用します。これは(void)、空の括弧はすでに非プロトタイプ宣言を意味するためです。int main(void)プロトタイプもそうですが、そうではint main()ありません。

非プロトタイプ宣言は「時代遅れ」です。つまり、理論上は将来の言語標準から削除される可能性があります。しかし、これらは 1989 年以来廃止されており、2011 年の新しい ISO C 標準でさえ、委員会はそれらを削除するのに適しているとは考えていません。

于 2012-01-11T21:55:38.343 に答える
2
int power(int m, int n);

power関数のプロトタイプ形式での宣言です。関数宣言は、関数が持つパラメーターの数、関数パラメーターの型、および関数の戻り値の型をコンパイラーに通知します。

C では、関数識別子を宣言する前に使用することはできません。

于 2012-01-11T21:52:22.977 に答える
2

これは、関数が実際に実装される前に関数が使用されるため、関数インターフェイスをpublicにする前方宣言です。main()

呼び出し可能な API を公開するのと同様の機能を提供するヘッダー ファイル#include---しかし、コードは通常、K&R イントロの章のこの単一ファイルの例にあるように、同じコンパイル ユニットを介してではなく、ライブラリで提供されます。 .

于 2012-01-11T21:52:58.117 に答える
1

その行を先頭に含めないと、プログラムがいつpower(2,i)主電源に到達するかはまだ宣言されていません。プログラムは上から下に読み込まれ、宣言を一番上に置くことで、コンパイラーは「定義が来ている」ことを認識します。

于 2012-01-11T21:52:42.733 に答える
1

その行は単なる関数プロトタイプです。これは、すべてがリンクされたときに存在するシグネチャを持つ関数をコードで使用できるようにする前方宣言です。これがないと、main()関数は関数を使用しようとしますpower()が、実際にはソース ファイルで後で定義されていないため、コンパイラはまだそれを認識していません。

于 2012-01-11T21:53:14.840 に答える
0

あなたが参照している一番上の行は関数プロトタイプです。唯一の目的は、コンパイラが作業をチェックできるようにすることです。つまり、正しい型と引数の数を渡すことによって、関数を正しく使用していることを確認することです。それだけです。そのため、それを削除してもコードはコンパイルされます。削除することで行うことは、コンパイラの参照を削除することだけなので、作業をチェックできません。また、それを削除すると、間違ったタイプの引数を渡して実行時エラーを見つけるのが困難になったり、プログラムがクラッシュしたりする可能性があります。しかし、それをそのままにしておくと、コンパイル時にコンパイラがそのようなエラーにフラグを立てることができ、悲しみを救うことができます. そして、誰かの悲しみを救うことは良いことです。

その後、C99 標準では、コードをコンパイルするために関数プロトタイプを提供すること (または最初に関数を定義すること) を必須にすることを決定したため、コンパイラーに作業をチェックさせることが強制されました。

于 2012-01-12T08:13:21.040 に答える