K&R関数宣言とANSI関数宣言の違いは何ですか?
3 に答える
K&R 構文は廃止されました。非常に古いコードを維持する必要がない限り、省略できます。
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
従来の K&R スタイルの宣言/定義
カーニハンとリッチーが「The C Programming Language」を最初に発表したとき、C はまだ完全な機能のプロトタイプを提供していませんでした。関数の前方宣言は存在しましたが、戻り値の型を示すことのみを目的としていました。を返す関数についてはint
、C99 までは必要ありませんでした。
C89 までに、パラメーターの型 (および暗黙のうちにその数) も指定する関数プロトタイプの概念が追加されました。プロトタイプも関数宣言の一種であるため、プロトタイプではない関数宣言に対して「K&R 関数宣言」という非公式の用語が使用されることがあります。
// K&R declarations, we don't know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();
// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);
// K&R definition of a function
int foo(a)
int a; // parameter types were declared separately
{
// ...
return 0;
}
// Modern definition of a function
float bar(int a, float b)
{
// ...
return 0.0;
}
偶然のK&R宣言
C を初めて使用する人は、完全なプロトタイプを使用するつもりのときに誤って K&R 宣言を使用する可能性があることに注意してくださいvoid
。
関数を次のように宣言および定義すると、
// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters
// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
// Missing "void" in the parameter list of a definition is undesirable but not
// strictly an error, no parameters in a definition does mean no parameters;
// still, it's better to be in the habit of consistently using "void" for empty
// parameter lists in C, so we don't forget when writing prototypes.
{
// ...
return 0;
}
...実際には、パラメーターを取らない関数のプロトタイプを指定していませんが、未知の型の未知の数のパラメーターを受け入れる関数の K&R スタイルの宣言を指定しています。
AnT は、同様の質問に対するこの回答で、この構文は非推奨ですが、C99 の時点ではまだ合法であることに注意しています (また、不明な数と型のパラメーターを持つ関数への関数ポインターには、未定義の動作のリスクが高いものの、潜在的なアプリケーションがまだあります)。そのため、適切なプロトタイプなしで関数が宣言または呼び出された場合、準拠コンパイラはせいぜい警告を生成します。
プロトタイプなしで関数を呼び出すと安全性が低下します。コンパイラは、正しい数と型のパラメーターが正しい順序で渡されたことを確認できないためです。呼び出しが実際に正しくない場合、未定義の動作が発生します。
もちろん、パラメーターなしの関数を宣言および定義する正しい方法は次のとおりです。
// Modern declaration of a parameterless function.
int qux(void); // "void" as a parameter type means there are no parameters.
// Without using "void", this would be a K&R declaration.
// Modern definition of a parameterless function
int qux(void)
{
// ...
return 0;
}
int
従来の K & R スタイルでは、値を返す関数の型修飾子は不要であるということを追加したいだけです。
単純な HelloWorld プログラムの最新の C11 表記を考えてみましょう。
int main(int argc, char **argv) {
printf("hello world\n");
return 0;
}
これは、K & R 記法スタイルと同等です。
main(argc, argv)
int argc;
char **argv;
{
printf("hello world\n");
return 0;
}
int
beforemain()
は無視されますが、コードはコンパイルされることに注意してください。これは K & R 定義の一部です。
ウィキペディアの引用:
C の初期のバージョンでは、関数定義の前に使用する場合、int 以外の値を返す関数のみを宣言する必要がありました。以前の宣言なしで使用された関数は、その値が使用された場合、型 int を返すと想定されていました。
--出典: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
これは間違いなく従来のコーディング スタイルであり、明確さの問題から避けるべきですが、古いアルゴリズムの教科書では、この種の K & R スタイルが好まれることがよくあります。