このコードが C では正常にコンパイルされ、C++ ではエラーが発生するのはなぜですか?
int main;
ホスト環境で標準に準拠していますか? 基準を引用できますか?
gccでテストしました。
このコードが C では正常にコンパイルされ、C++ ではエラーが発生するのはなぜですか?
C++ の名前マングリングが原因です。基本的に、すべての実用的な実装では、リンカーは名前付きのシンボルmain
(またはそのバリアント、_main
Apple のプラットフォームで見たことがある) を探します - C では、main()
関数または名前付きの extern ストレージ変数の main
いずれかです- ポイントは通常C 実装 (コンパイラ、ツールチェーン) は、リンカー レベルで変数と関数を区別しません。そのため、名前付きの変数または関数のいずれかである 1 つのシンボルを提供するmain()
だけで十分と思われる場合があります。実際、ホスト環境では、標準に従って、結果として得られるプログラム (実行可能ファイル) は適合しません。これは、main()
機能を実装する必要があるためです。
C++ では、通常、(関数のオーバーロードなどの C++ の機能を実現するために) 名前マングリングが使用されます。これは、コンパイラが実行可能ファイル内の結果のシンボルに、その型に応じて異なる名前を付けることを意味します。変数、署名が異なる関数、およびその他の状況。そのため、リンカーは基本的に、期待されるint main(int, char *[])
関数に対応するシンボルを見つけられず、エラー メッセージを発行します。
規格に適合していますか?
関数を定義しないことmain()
はそうではありません (最初の部分を参照してください)。私が知る限りmain
、main 関数と一緒に名前を付けた変数を持つことは有効な C++ ですが、それは確かに悪い習慣です。
標準を引用できますか?
はい、どうぞ(私の強調):
C++ 98、段落 3.6.1:
プログラムには、プログラムの指定された開始であると呼ばれるグローバル関数が含まれます。関数を定義するために独立した環境のプログラムが必要かどうか
main()
は、実装によって定義されます。main()
C99、パラグラフ 5.1.2.2.1
5.1.2.2.1 プログラムの起動
1 プログラムの起動時に呼び出される関数の名前は main です。実装は、この関数のプロトタイプを宣言していません。私
ISO/IEC 14882:1998(E) (別名 C++98) から、3.6.1メイン関数:
実装は、メイン関数を事前定義してはなりません。この関数はオーバーロードされません。2 戻り値の型は int 型でなければなりませんが、それ以外の場合、その型は実装定義です。すべての実装は、main の次の定義の両方を許可する必要があります。
int main() { /* ... */ }
後者int main(int argc, char* argv[]) { /* ... */ }
の形式では、argc は、プログラムが実行される環境からプログラムに渡される引数の数になります。argc が非ゼロの場合、これらの引数は argv[0] で提供されます。
argv[argc-1] はヌル終端マルチバイト文字列 (NTMBS) (17.3.2.1.3.2) の最初の文字へのポインターとして使用され、argv[0] は使用される名前を表す NTMBS の最初の文字へのポインターでなければならないプログラムまたは "" を呼び出します。argc の値は非負でなければなりません。argv[argc] の値は 0 でなければなりません
。]
関数 main は、プログラム内で使用してはなりません (3.2)。main のリンケージ (3.5) は 3 実装定義です。main を inline または static と宣言するプログラムは形式が正しくありません。名前 main は予約されていません。[例: メンバー関数、クラス、および列挙型は、他の名前空間のエンティティと同様に、main と呼ぶことができます。]
int main;
上記に準拠していません(「すべての実装は、main の次の定義の両方を許可する必要があります」、「関数 main はプログラム内で使用してはなりません(3.2)」)。
はい、有効です。
という名前の整数を宣言しmain
ます。
私は、1つを見つけたと思います。解決策ではありませんが、覚えておくべきポイント
gcc -Wall -Werror <file.c>
エラーとして扱われる警告が表示されます。
main is usually a function name
-Wall
したがって、すべての警告も表示できるようにコンパイルするのが最善です