2009-05-05 10 views
15
int main() 
{ 
    int var = 0;; // Typo which compiles just fine 
} 
+33

をなぜ彼らは違法でなければなりませんか?それはVBの空白行を違法にするのと同じです。 – dreamlax

+1

完全に異なる2つの言語のルールを比較して、特定の言語設計の選択肢を検証することはできません。 – sharkin

+4

ドリームラックスのポイント(私は思う):害は何ですか? –

答えて

13

これはCとC++がNOPを表現する方法です。

+0

タイトバジェットマイクロコントローラシステムで最も重要なのはどれですか。 – jpinto3912

+22

@ jpinto3912:実際には、 ';'はターゲットプラットフォームの 'NOP'命令ではなく、ほとんどすべての命令をコンパイルしません。 –

+0

私はそれを疑う。本質的である可能性が高い、またはasm。命令なし!= NOP。 – Nick

8

私は言語のデザイナーではありませんが、答えは「どうしてですか?」です。言語設計の観点から、ルール(すなわち、文法)はできるだけ単純であることが望ましい。

は、 "空の表現は" 用途を持っていることは言うまでもありませんつまりため

(I = 0;私< INSANE_NUMBER;私は++します);

デッドウェイト(いい使用ではありませんが、それにもかかわらず)です。

EDIT:この回答のコメントに指摘されているように、その塩の価値のあるコンパイラはおそらくではありません。はこのループで待機しています。しかし、もし私が(奇妙なことに)データ構造のトラバーサルを行っているのを見たことのあるヘッド自体(i ++以外)で役に立つものがあれば、空のボディを使ってループを構築することができます(/ "for"構造を悪用する)。

+3

これは実際に待ちますか?何も起こらないので、コンパイラはループを最適化できますか? – Tom

+0

良い質問です。あなたがそれに言及したので、私は知らない。私が知っているのは、それは*すべきだということです。 :) –

+0

@Tom:良い質問です。少なくとも標準では、C++では実行時間がシステムの「観測可能な振る舞い」の一部ではないため、理論的にはコンパイラがこれを最適化できると考えています。しかし、もし私が揮発性なら、この最適化は禁止されています。 –

3

最も一般的なケースは、おそらく

int i = 0; 
for (/* empty*/; i != 10; ++i) { 
    if (x[i].bad) break; 
} 
if (i != 10) { 
    /* panic */ 
} 
0
while(1){ 
    ; /* do nothing */ 
} 

であるあなたが座って何もしないようにしたいがございます。イベント/割り込み駆動の組み込みアプリケーション、またはスレッドを設定して最初のコンテキストスイッチを待っているときなど、関数を終了させたくない場合。

例: http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523

+7

CPU冷却テスト? –

+6

セミコロンは必要ありません! –

+0

は、通常言語間のベンチマーク戦で使用されます:) – gbjbaanb

10

それは、私たちはそれなしに住むことができる

for(;;) { 
    // stuff 
} 

のようなものを言うことができ、明らかですか?

+1

神はgotoを禁じます! –

+8

これは良い例ではありません。たとえば、2番目のセミコロンはステートメントを終了するために使用されないためです。 forの2番目の節は式です。それを空のままにすることは、真と同等にする特別なケースとして扱われます。 – newacct

+0

元の質問は表現に関するものであり、文に関するものではありません。 –

6

私は正直なところ、これが本当の理由かどうかわかりませんが、より理にかなっているのは、コンパイラ実装者の立場から考えることです。

コンパイラの大部分は、特殊なクラスの文法を分析する自動化ツールによって構築されています。有用な文法は空文を許可するのは当然のようです。あなたのコードのセマンティクスを変更しない場合、そのような "エラー"を検出するのは不要な作業のようです。コンパイラはこれらの文のコードを生成しないので、空の文は何もしません。

これは「壊れていない何かを修正しない」だけの結果であるように私には思える

...

+0

DMRのオリジナルのCコンパイラ(この構文の由来)は再帰的なコンパイルです。このようなコンパイラは通常手作業で書かれているので、ここでは大したことは問題ではないと思います。 –

+0

これは、この種のことが起こる可能性が高いと思われます。 rdpをハンドコーディングしている場合は、文法の中のすべてのプロダクションのための関数を書いています。次の入力にマッチする仕事です...式やその他のものがステートメントを構成し、式やその他のものが終わることがある(究極のセミコロンが続くのを除いて)入力を消費すると、パーサはそのような文を認識します。 Idk、これが本当の理由なら、それはそれを推論する合理的な方法のように思えます。 (私は巨大なr.d.p.を書いたことはありませんでしたが、前に書いたことがあります)。 – Tom

+0

私はC言語のためのある特定のYacc文法を見ています。空の文は余分な規則を必要とするので、その反対が真実であるようです。少なくともその文法は、その言語では、そのツールです。 –

31

NDEBUGが定義されているとき、他にどのようにassert(foo == bar);何もダウンしてコンパイルだろうか?

+0

ここでの唯一の説明は+1です。 –

+3

さて、 '0'や'((void)0) 'のようなものにコンパイルさせるのはおそらく大丈夫かもしれませんが、とにかくコンパイルするのが私に起こります... –

+2

' do {} while(0) ' – curiousguy

5

あなたは

while (fnorble(the_smurf) == FAILED) 
    ; 

なく

while (fnorble(the_smurf) == FAILED) 
    do_nothing_just_because_you_have_to_write_something_here(); 

のようなことを行うことができるようにしたい。しかし!このように、同じ行に空のステートメントを記述しないでください。

while (fnorble(the_smurf) == FAILED); 

セミコロンを欠場することは容易であることから、読者を混乱させ、したがって、次の行であることを考えるために非常に良い方法だことループの本体覚えておいてください:プログラミングとは、実際にはコミュニケーションに関することです。コンパイラではなく、コードを読む他の人とのコミュニケーションです。 (!や自分自身と、3年後)

5

OK、私はあなたが実際に使用することができます最悪のシナリオにこれを追加します:

for (int yy = 0; yy < nHeight; ++yy) 
{ 
    for (int xx = 0; xx < nWidth; ++xx) 
    { 
     for (int vv = yy - 3; vv <= yy + 3; ++vv) 
     { 
      for (int uu = xx - 3; uu <= xx + 3; ++uu) 
      { 
       if (test(uu, vv)) 
       { 
        goto Next; 
       } 
      } 
     } 

    Next:; 
    } 
} 
+1

+1便利な例:gotoラベルにはステートメントが必要ですが、まれにgotoが必要な場合があります。ループの最後にラベルが必要な場合が多いため、NOPステートメントが必要です。あなたはgotosに対抗するかもしれませんが、余分な変数やif()ステートメントを使って個々のループを個別に終了するのではなく、深く入れ子になったループを終了するためにgotoを使用することが望ましい場合があります。 – Darren

2

を使用する場合は「;」 1つの事についても気をつけてください。これはokです:

a ? b() : c(); 

しかし、これはコンパイルされません。

a ? b() : ; ; 
+2

これは、 ';'は*式*を置き換えることができないためです。 *文の場合のみ*。 – namezero

関連する問題