2009-04-01 10 views
7

私は現在C(C++ではない)を書いています。 MicrosoftのCコンパイラは、すべての変数を関数の先頭に宣言する必要があります。なぜマイクロソフトのCコンパイラは関数の始めに変数を必要としますか?

たとえば、次のコードはコンパイルを渡しません。

int foo(int x) { 
    assert(x != 0); 
    int y = 2 * x; 
    return y; 
} 

コンパイラは、コードがそれ以下のように変更された場合

error C2143: syntax error : missing ';' before 'type' 

を言って、三行目でエラーを報告します編集をパスします:

int foo(int x) { 
    int y; 
    assert(x != 0); 
    y = 2 * x; 
    return y; 
} 

ソースファイル名を.c.cppに設定すると、コンパイルも正しく行われます。

コンパイラの厳密さを無効にするオプションがあると思われますが、見つけられませんでした。誰もこれを助けることができますか?

ありがとうございます。

私は、Visual Studio 2008 SP1に同梱されているcl.exeを使用しています。

投稿日:

ありがとうございました!私はMicrosoftのcl.exeでC89に住んでいなければならないようだ。

答えて

33

C89標準を使用しているようです。すべての変数をコードよりも前に宣言する必要があります。リテラルなどで初期化することはできますが、コードと変数を混在させることはできません。

C99をどこかで有効にするには、コンパイラのフラグが必要です。これは、使用していた動作を得ることができます。

EDIT:クイックグーグルはC99を有効にするために有望ではありません。あなたはC89(それほど悪くない)またはより良いCコンパイラ(それが良いだろう)を見つける必要があります。

+0

+1。しかし、悪い昔の私に思い出させるためではありません。 –

+0

C99オプションをオンにするオプションについては、cl.exeのヘルプを検索しています。しかし、これまでのところ私はそれについての手がかりを得ていません。 すべての変数を先頭に宣言する必要があり、非常に不便です。 私のコードをコンパイルするためにgccを使用するとうまくいきます。これは、cl.exeがC99標準をサポートしていないことを意味しますか? – yinyueyouge

+0

Ryan:cl.exeはC99をサポートしていないようです。これは信じられないほどです。それはほぼ10年経ちました! – dwc

1

このエラーに基づいて使用する必要があるC89標準では、ブロック内のステートメントの実行を開始する前に変数を宣言する必要があります。

コンパイラはこれらのファイルを同じ制限を持たないC++ファイルとして扱うため、.cpp拡張ファイルでこの問題は発生しません。

あなたのassertステートメントはコードなので、同じブロック/スコープ内の変数を宣言することはできません。

int foo(int x) { 
    assert(x != 0); 
    { 
     int y = 2 * x; 
     return y; 
    } 
} 

を、私はそれをお勧めしません:

技術的にはあなたがこれを行うことができます。

+1

古代(C89)古代とは対照的に、この制限はありません。 –

2

C99についてはわかりませんが、以前のバージョンの言語では、ローカル変数は{}ブロックの先頭に宣言する必要があります。

1

C90には、すべての変数を最初のステートメントの前に宣言する必要があります。これはC99のケースではありません。私はコンパイラがC99用のスイッチを持っているかどうかを見ることができると思います。

0

C仕様では、実行可能コードの最初の行より前にすべての変数を宣言する必要があります。コンパイラは仕様に準拠しています。いくつかのコンパイラはこの点で寛大です。

+3

C99がこれを変更しました。 – Richard

1

これにより、アセンブリへの翻訳が容易になります。関数を入力すると、すべての変数がスタックにプッシュされるため、他の場所で行うことを心配する必要はありません。

+0

それはどんな場合でも難しくありません。コードを生成する前にシンボルテーブルを作成することに問題はありません。 –

+0

変数は「スタックにプッシュ」されません。スタックポインタは単純に変更されます。また、関数の先頭にあるすべての変数を宣言しても、オプティマイザはスタック割り当てのタイミングと方法を決める余裕があります。 – snemarch

7

Microsoft CコンパイラはC89コンパイラであり、もうアップグレードされません。標準C99はafaikが計画していません。 C99のプレーンC(ブロックの先頭にない変数)には、別のコンパイラまたはC++拡張を使用します。

+0

C++標準とC++ 0x標準(MSVC++が準拠する予定)がC99に準拠した変更を行うC99の変更がいくつかありましたが、C++はCではありません。 C99規格の後に。 –

1

C仕様に関するコメントに同意します。コンピュータが大量のメモリを持たない時代にCが作成されたことを忘れないでください。

これに対処する1つの方法は、ソースファイルを上から下へ一度に読み込むことができるようにすることでした(これは、.hファイルが使用される理由です)関数は実際には存在しますが、参照された最初の後のどこかにある可能性があります)。

変数をどこにでも宣言できるコードよりも、スコープの先頭で変数を宣言するコードのコンパイラを作成する方が簡単かもしれません。

3

これは、MSCがサポートしているCのバージョンです。しかし、純粋主義者を怒らせる準備ができていれば、コンパイラにC++としてコンパイルを強制することができます。

これは純粋なCとほとんど違いがありません(void *ポインタのキャストと名前修飾の変更に関するいくつかの規則があります)が、便利なハイブリッドを与えるかもしれません。生成されるコードはほぼ同じです。この変更を行うことで効率の魔法の損失(または利得)はありません。

あなたはC.

+2

おそらく、コンパイラフラグを "C++マイナス例外"に設定したいと思うかもしれません。 – MSalters

1

を使用することに熱心だ、なぜあなたはそれはMSはそれがデフォルトでオフだ場合でも、(Cコンパイラの拡張機能として混合宣言と文を実装していないことを恥だと言うしませんし、スイッチを入れる必要があります)。私は確信していませんが、他の非C99コンパイラではこれがかなり一般的な拡張だと思います。私はMSVCでコンパイルするためにソースとサンプルを修正しなければならないことがよくあります。

私は実装するのが比較的簡単だと思いますが、もちろんC++のために既に行っています。

関連する問題