246

何が良いですか:void foo()またはvoid foo(void)?ボイドがあると醜くて一貫性がないように見えますが、それは良いと言われています。これは本当ですか?

編集:古いコンパイラの中には奇妙なことをするものがあることは知っていますが、GCCだけを使用している場合は、void foo()大丈夫ですか?foo(bar);その後、受け入れられますか?

4

6 に答える 6

302
void foo(void);

これは、Cで「パラメーターなし」と言う正しい方法であり、C++でも機能します。

だが:

void foo();

CとC++では異なることを意味します!Cでは「未知のタイプのパラメータをいくつでも取ることができる」という意味であり、C++では。と同じ意味foo(void)です。

可変引数リスト関数は本質的にタイプセーフではないため、可能な限り避ける必要があります。

于 2009-03-28T23:48:30.727 に答える
98

C でパラメータを指定する方法は 2 つあります。1 つは識別子リストを使用する方法で、もう 1 つはパラメータ タイプ リストを使用する方法です。識別子リストは省略できますが、型リストは省略できません。したがって、ある関数が関数定義で引数を取らないと言うには、(省略された) 識別子リストを使用してこれを行います

void f() {
    /* do something ... */
}

そして、これはパラメーターの型のリストで:

void f(void) {
    /* do something ... */
}

パラメーターの型リストでパラメーターの型が 1 つだけ void の場合 (その場合、名前がない必要があります)、それは関数が引数を取らないことを意味します。しかし、関数を定義するこれら 2 つの方法には、宣言する内容に関して違いがあります。

識別子リスト

最初のものは、関数が特定の数の引数を取ることを定義しますが、識別子リストを使用するすべての関数宣言と同様に、カウントも必要なものの型も伝達されません。したがって、呼び出し元は事前にタイプとカウントを正確に知っている必要があります。そのため、呼び出し元が何らかの引数を指定して関数を呼び出した場合、動作は未定義です。たとえば、呼び出された関数が制御を取得したときに別のレイアウトを想定しているため、スタックが破損する可能性があります。

関数パラメーターで識別子リストを使用することは非推奨です。これは昔から使用されており、今でも多くの製品コードに存在しています。それらは、これらの引数の昇格のために重大な危険を引き起こす可能性があり (昇格された引数の型が関数定義のパラメーターの型と一致しない場合、動作も未定義です!)、もちろん安全性ははるかに低くなります。voidそのため、唯一の宣言と関数の定義の両方で、パラメータのない関数には常にthingyを使用してください。

パラメータ型一覧

2 番目のものは、関数がゼロ引数を取り、それを通信することも定義します。これは、関数が a と呼ばれるパラメーター型リストを使用して宣言されるすべての場合と同様prototypeです。呼び出し元が関数を呼び出して何らかの引数を与えると、それはエラーであり、コンパイラは適切なエラーを吐き出します。

関数を宣言する 2 番目の方法には、多くの利点があります。もちろん、パラメーターの量とタイプがチェックされます。もう 1 つの違いは、コンパイラはパラメーターの型を認識しているため、引数の暗黙的な変換をパラメーターの型に適用できることです。パラメーターの型リストが存在しない場合、これは実行できず、引数は昇格された型に変換されます (これは、既定の引数の昇格と呼ばれます)。たとえば、char_ _intfloatdouble

関数の複合型

ちなみに、ファイルに省略された識別子リストとパラメーター型リストの両方が含まれている場合は、パラメーター型リストが「優先」されます。最後の関数の型にはプロトタイプが含まれています。

void f();
void f(int a) {
    printf("%d", a);
}

// f has now a prototype. 

それは、両方の宣言が矛盾することを何も言っていないからです。ただし、2番目にはさらに言いたいことがありました。つまり、1 つの引数が受け入れられます。逆でも同じことができる

void f(a) 
  int a;
{ 
    printf("%d", a);
}

void f(int);

1 つ目は識別子リストを使用して関数を定義し、2 つ目はパラメーター型リストを含む宣言を使用してそのプロトタイプを提供します。

于 2009-03-29T00:41:48.713 に答える
25

void foo(void)明示的に言うので、より良いです:パラメータは許可されていません。

void foo()これは、少なくともこれが関数の定義ではなく関数の宣言である場合に、(一部のコンパイラーでは)パラメーターを送信できることを意味します。

于 2009-03-28T23:46:12.840 に答える