function()とfunction(void)の違いは何ですか?


27

次のようなパラメータとして何も受け取らない関数を書くことは良い習慣だと聞いたことがあります。

int func(void);

しかし、それを表現する正しい方法は次のように聞こえます。

int func();

CとC ++の両方でのこれら2つの関数宣言の違いは何ですか?


5
これは、とりわけ、サイトのネットワーク上の千の他の質問の重複であるstackoverflow.com/questions/18167390/...
ラースViklund

@LarsViklundは、このサイトに質問がある場合にのみ重複します。私はそれを見つけることができないので、何がSOにあるかに関係なく、これは複製ではありません。おそらく、この質問を道しるべとして維持する価値はあります。


1
@LightnessRacesinOrbit チャット議論し、いくつかの編集でそれを維持することにしました。

回答:


17

この点でCとC ++は異なります。

C 2011オンライン標準

6.7.6.3関数宣言子(プロトタイプを含む)
...
10 voidリスト内の唯一の項目としての型の名前のないパラメーターの特殊なケースは、関数にパラメーターがないことを指定します。
...
14識別子リストは、関数のパラメーターの識別子のみを宣言します。その関数の定義の一部である関数宣言子の空のリストは、その関数にパラメーターがないことを指定します。その関数の定義の一部ではない関数宣言子の空のリストは、パラメーターの数またはタイプに関する情報が提供されないことを指定します。145)

つまり、関数宣言の空のパラメーターリストは、関数が指定されていない数のパラメーターを受け取ることを示し、関数定義の空のパラメーターリストは、関数がパラメーターを受け取らないことを示します。

T foo( void ); // declaration, foo takes no parameters
T bar();       // declaration, bar takes an *unspecified* number of parameters

T foo( void ) { ... } // definition, foo takes no parameters
T bar() { ... }       // definition, bar takes no parameters

Cに関する限り、関数の宣言または定義で空の識別子リストを使用しないでください。関数がパラメーターを取得することを意図していない場合voidは、パラメーターリストで使用して指定します。

オンラインC ++標準

8.3.5関数[dcl.fct]
...
4 parameter-declaration-clauseは、関数が呼び出されたときに指定できる引数とその処理を決定します。[ 注:パラメータ宣言句は、関数呼び出しで指定された引数を変換するために使用されます。5.2.2を参照してください。— end note ] parameter-declaration-clauseが空の場合、関数は引数を取りません。非依存型の名前のない単一のパラメーターで構成されるパラメーターリストvoidは、空のパラメーターリストと同等です。この特別な場合を除いて、パラメーターはtypeを持ちませんcv void。もしパラメータ宣言節省略記号または関数パラメータパック(14.5.3)で終了する場合、引数の数は、デフォルト引数を持たず、関数パラメータパックではないパラメータの数以上でなければなりません。構文的に正しい場合、および「...」が抽象宣言子の一部ではない場合、「、...」は「...」と同義です。[ 例:宣言
    int printf(const char*, ...);
さまざまな数とタイプの引数で呼び出すことができる関数を宣言します。
    printf("hello world");
    printf("a=%d b=%d", a, b);
ただし、最初の引数は、次のように変換できる型でなければなりませんconst char*end example ] [ 注:標準ヘッダーに<cstdarg>は、省略記号(5.2.2および18.10を参照)を使用して渡される引数にアクセスするためのメカニズムが含まれます。— 終了ノート ]

C ++の場合、宣言または定義のいずれかの空のパラメーターリストは、関数が引数を取らないことを示し、のパラメーターリストを使用するのと同等ですvoid


35

Cでは、空のパラメーターリストを持つ関数は、引数に何でも使用()できます。文字通り何でも。これは通常、可変数の引数を取ることができる関数を実装するために使用されますが、最近では、これらの関数に対してより明示的な省略記号構文を使用することが望ましいと考えられています。(...)

Cでは、パラメーターリストを持つ関数は、引数に対して(void)明示的に何も受け取りません。つまり、コンパイラーは、何かを渡そうとした場合に間違いを犯したことを実際に通知できることを意味します。

C ++では、これらの関数宣言は同等です。空白のパラメーターリストは、「パラメーターなし」と同じ意味voidです。


Re:「これは通常、可変数の引数を取ることができる関数を実装するために使用されます」:これについて確かですか?非可変数関数の前方宣言と可変数関数の明示宣言に明示的なパラメーターリストを使用したプログラムを見たことがないと思い()ます。この規則を使用するプログラムの例はありますか?
-ruakh

4
AC可変引数関数は、必要があると定義される...構文、それは少なくとも1つのという名前のパラメータを持っている必要があります。このような関数を定義すると()、未定義の動作が発生します。また、関数の本体が<stdarg.h>パラメータ値を読み取るために定義されたマクロを使用する方法はありません。これは、1989/1990標準以来のケースです。
キーストンプソン

@KeithThompson:この質問とこの答えは、関数定義ではなく、事前宣言について述べています。
-ruakh

3
@ruakh:未定義の動作を避けるために、構文を使用して可変長関数を宣言および定義する必要があります...
キーストンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.