web-dev-qa-db-ja.com

int main()とint main(void)の違いは?

次の意味は何ですか:

_int main(void) {...} 
_

VS

_int main() {...}
_

int main() {...}は、mainが(コマンドラインから)パラメーターを受け取らないことを意味すると思いますが、

_int main(int argc, char *argv[])
_

します。

しかしint main(void) {...}はどういう意味ですか? voidは何を表していますか?

here を見てきましたが、どういうわけか別の質問です。

55
JAN

C++では、違いはありません。


Cでは、違いは疑わしいです。後者のバージョン(voidのないバージョン)は技術的には単なる一般的な実装拡張であり、標準の文言により標準で動作することは保証されないと主張する人もいます。ただし、標準では、関数の定義では、空のパラメーターセットには明確に定義された動作があると明確に示されています。つまり、関数はパラメーターを取得しません。したがって、このようなmainの定義は、標準の次の説明と一致します。

[メイン]は、戻り値の型intで定義され、パラメーターは定義されません。

ただし、2つの間に顕著な違いがあります。つまり、voidのないバージョンは、関数の正しいプロトタイプを提供できません。

// this is OK.
int main()
{
  if (0) main(42);
}

// this requires a diagnostic to be shown during compiling
int main(void)
{
  if (0) main(42);
}

ああ、そして完全に:voidはすべての関数宣言子で次の意味を持ちます:

(6.7.6.3p10)リスト内の唯一の項目であるvoid型の名前のないパラメーターの特殊なケースは、関数にパラメーターがないことを指定します。

50
eq-

Cでは、prototype(ただしC++ではない)空の引数リストは、関数がany 引数(関数の定義では、引数がないことを意味します)。 C++では、空のパラメーターリストは引数がないことを意味します。 Cでは、引数を取得しないために、voidを使用する必要があります。より良い説明については this questionをご覧ください。

6
Linuxios

関数foo(void)foo()を持つC++では同じことです。ただし、Cでは異なります。foo(void)は引数のない関数であり、foo()は引数が指定されていない関数です。

C++では違いはなく、両方とも同じです。

どちらの定義もCでも機能しますが、mainをパラメーターなしでのみ呼び出すことができることを明確に指定しているため、voidを持つ2番目の定義は技術的に優れていると見なされます。 Cでは、関数のシグネチャで引数が指定されていない場合、関数を任意の数のパラメーターで、またはパラメーターなしで呼び出すことができます。たとえば、次の2つのCプログラムをコンパイルして実行してみてください(ファイルを.cとして保存することを忘れないでください)。

3
Dila Gurung

まず第一に、ホストされたシステムと自立型システムで許可されているものに違いがあります ここに表示

ホストシステムの場合、5.1.2.2.1プログラムの起動が適用されます。

プログラムの起動時に呼び出される関数の名前はmainです。実装は、この関数のプロトタイプを宣言しません。戻り値の型intで定義され、パラメーターはありません。

int main(void)

...(argv/argcなどのスタイルに関するテキストが続きます)。

興味深い部分は「パラメーターなし」です。 int main()int main (void)は、両方とも関数宣言子であり、パラメーターがないため、現在は同等です。以下が適用されます(6.7.6.3):

10リスト内の唯一の項目としてのvoid型の名前のないパラメーターの特殊なケースは、関数にパラメーターがないことを指定します。

/-/

14識別子リストは、関数のパラメーターの識別子のみを宣言します。 その関数の定義の一部である関数宣言子の空のリストは、関数にパラメーターがないことを指定します。関数宣言子の空のリストは、パラメータの数またはタイプに関する情報が提供されないことを指定するその関数の定義の一部ではありません。145)

私を強調して、太字のテキストはint main()に適用されるものです。また、テキストの最後に「145」という「今後の言語の指示」を参照してください。

6.11.6関数宣言子

空の括弧を持つ関数宣言子(プロトタイプ形式のパラメーター型宣言子ではない)の使用は、廃止された機能です。

そして、ここに違いがあります。関数宣言子であるため、int main()bad styleです。これは、次のバージョンでの動作が保証されていないためです。 C標準。 C11では廃止された機能としてフラグが付けられます。

したがって、ホストされたシステムでは常にint main (void)を使用し、現在は2つの形式が同等であってもint main()を使用しないでください。


C++では両方の形式は完全に同等ですが、主観的、美容上の理由からint main()が好ましいスタイルです(Bjarne Stroustrupはそう言っています...これはおそらく、特定の方法で何かをする理由を説明するためのかなり悪い根拠です) )。

2
Lundin

C++では、2つの間に違いはなく、int main()mainの正当な署名および戻り値の型です。

1
juanchopanza

私はスレッドが古いことを知っていますが、この質問は数年前に私を悩ませていたので、私は半セントを投げたいと思っていました(その場合)。

C関数は、va_argsを使用しない限り、コンテキストに関係なく一定量の引数を持っているものとして扱います。つまり、私は主に常にプロトタイプを持っていると信じています:

int main(int argc, char **argv).

引数が渡されなくても、メイン関数には関数のオーバーロードがないため、関数にはスタック上にこれらの引数があります。

Cには、引数が存在しないふりをするだけでプリミティブなオーバーロードを行う機能があります。この場合、引数はまだ渡され、スタック上にありますが、アクセスすることはないため、ソースコードのサイズを小さくするだけです。

Int main()と言うことは、関数にパラメーターがある可能性があることを知っているが、それらを使用していないことを意味しているため、int main()と記述します。

Int main(void)と言うと、main CERTAINLYには引数がなく、2つの異なる関数プロトタイプがあることを意味します。

int main(void);
int main(int argc, char **argv);

Cには関数のオーバーロードがないため、これはやや誤解を招く可能性があり、main(void)を含むコードを信用しません。 main NEVERがパラメーターを取らなかった場合、私はそうしません。その場合、main(void)は完全にOKです。

注:一部の実装では、envなどのargcおよびargvよりも多くのパラメーターがmainにありますが、これらは2つのパラメーターだけであると明示的に言っていないことを知っているため、これは気になりませんが、最小のパラメーターですそして、もっと多くても大丈夫ですが、少なくはありません。これは、この関数にはパラメーターがないので私に怒鳴るint main(void)と言うのとは対照的です。

ここに私の基本コードがあります:

/* sample.c - build into sample. */
#include <stdio.h>

int main(void)
{
    int _argc = *((int *)2686800);
    char ***_pargv = (char ***)2686804;
    int i;

    for (i = 1; i < _argc; ++i) {
        printf("%s ", (*_pargv)[i]);
    }

    return 0;
}

./sample私は明らかに引数を持っています

関数は、関数プロトタイプにvoidを入力することではないことを明示的に示すことはありませんが、明らかに引数が渡されます。

Eq-上記のように:

(6.7.6.3p10)リスト内の唯一の項目であるvoid型の名前のないパラメーターの特殊なケースは、関数にパラメーターがないことを指定します。

したがって、関数が引数としてvoidを持っているが、実際にはスタック上に引数を持っていると言うことは矛盾です。

私のポイントは、引数がまだそこにあるということです。したがって、mainに引数がないことを明示的に主張することは不正です。正直な方法はint main()と言うことです。これは、パラメーターの数については何も主張せず、気にするパラメーターの数だけを主張します。

注2:_argc、_pargvはシステムに依存します。値を見つけるには、このプログラムを実行して値を見つける必要があります。

/* findargs.c */
#include <stdio.h>

int main(int argc, char **argv)
{
    printf("address of argc is %u.\n", &argc);
    printf("address of argv is %u.\n", &argv);

    return 0;
}

これらの値は、特定のシステムに対して正しいままでなければなりません。

0
Dmitry

Type foo(void)を持つ関数プロトタイプはType foo()とまったく同じであり、2つの間に違いはありません。読みやすくするために前者を使用できます。

mainと同様に、引数を取るかどうかに関係なく、プログラムは__argv__argcGetCommandLine、または他のプラットフォーム/コンパイラーなど、他の手段を介してコマンドライン情報にアクセスできます。特定のシンボル。

0
Ajay