次のプログラムを検討してください(ライブデモ here を参照)。
#include <stdio.h>
int main(void)
{
int ; // Missing variable name
puts("Surprise");
}
私のコンパイラ、gcc 4.8.1は以下の警告を出します:
[警告]空の宣言に不要な型名があります[デフォルトで有効]
うまくコンパイルできるのはなぜですか?コンパイラエラーは発生しませんか? C++プログラムとしてコンパイルすると、g ++ 4.8.1で次のエラーが発生します。
[エラー]宣言は何も宣言していません[-fpermissive]
C標準は言う
Static_assert宣言以外の宣言では、少なくとも宣言子(関数のパラメーター、構造体または共用体のメンバー以外)、タグ、または列挙型のメンバーを宣言する必要があります。
C++は言う
単純な宣言では、オプションのinit-declarator-listは、クラス(条項9)または列挙を宣言する場合にのみ省略できます。
どちらの言語でもこれに違反するには、診断が必要です。標準では、コンパイラのエラーや警告については触れていません。警告は診断です。
あなたのコードは、CとC++の両方で違法です(つまり、エラーがあり、形式が正しくなく、制約違反です)。ある言語で「警告」が表示され、別の言語で「エラー」が表示される理由は、コンパイラとコンパイラの設定の癖にすぎません。結局のところ、どちらの言語も「警告」と「エラー」を正式に区別するものではありません。デフォルトの設定でのGCCは、Cモードではたまたま許容範囲が広いです(主に歴史的な理由による)。
使用する -pedantic-errors
GCCでは、Cコードでも「エラー」が表示されます。 (ご了承ください -pedantic-errors
は単にすべての「警告」を「エラー」に盲目的に変えるだけではありません。実際の制約違反のみを「エラー」として報告しようとします。)
宣言の構文は、(省略init-declarator-listおよびinit-declarator):
C11 6.7宣言
declaration: declaration-specifiers init-declarator-list opt ; static_assert-declaration declaration-specifiers: storage-class-specifier declaration-specifiers opt type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt function-specifier declaration-specifiers opt alignment-specifier declaration-specifiers opt
declaration-specifiersは再帰的に定義されていますが、それぞれoptが付いていることはオプションであることを示しています。
また、次の第6項には、
宣言指定子は、リンケージ、ストレージ期間、および宣言子が示すエンティティーのタイプの一部を示す一連の指定子で構成されます。 initdeclarator-listは、コンマで区切られた宣言子のシーケンスであり、それぞれに追加の型情報、初期化子、またはその両方が含まれる場合があります。宣言子には識別子(存在する場合)が宣言されています。
単語がある場合は注意してください。