1

学習目的で、次のコード スニペットを作成しました。

for(int i=0;i<10;i++)
{
  for(int j = 0;j<5;j++)        
  {
    //(i==j && i==3)? (goto found) : printf("stya here\n");        
    if(i==j && i==3){goto found;} else {printf("stay here\n");}
  }
}

found:
  printf("yes I am here");

しかし、内側のループ内の省略されたステートメントがエラーを出さないことをいつ発見したのだろうかと思いました。今では、if-else が常に?:演算子に置き換えられるとは限らないことに混乱しています。ここにある事実は何ですか?コメント付きのステートメントでエラーが発生するのはなぜですか?

4

5 に答える 5

10

?:演算子はの代わりではありませんif。式に対してのみ機能します。部分式とcondition ? expr1 : expr2式の両方が同じ型です (そして、式全体が同じ型です)。expr1expr2

gotoは表現ではなく、ステートメントです。

于 2012-06-30T09:19:45.053 に答える
3

なぜこれが構文的に機能しないのかを説明できるほど C に精通しているわけではありませんが、意図的に ?: 三項演算子形式は、制御フロー メカニズムとしてではなく、条件式 (結果を生成する) として意図されています。if ステートメントを使用すると、変数の値を選択したり、アプリケーションの流れを変更したりできます。例えば

//Change flow

if(x ==0)
{
   //do this
} 
else
{
 //goto some label
} 

また

//Change value
    if(x == 0)
    {
      y = 1;
    }
    else
    {
      y = 2;
    }

3 項は、条件式として 2 番目のケースのみを対象としています。

y = (x ==0) ? 1 :2;
于 2012-06-30T09:42:44.657 に答える
2

実際、goto と三項演算子でやろうとしていることは、コンパイラが拡張Statement Expressionsをサポートしている場合に可能です。名前が示すように、この拡張により、次のように、式または部分式内にステートメントを記述できます。

(rand() % 2) ? ({goto lbl1;}) : ({goto lbl2;});

これらのステートメントを使用すると、非常に便利です (主にマクロを最適化するため) が、私が示した例のように、非常に汚いコードになることがよくあります :)

したがって、他の回答を補完するために、C99/11では拡張なしでは不可能だと言いますが、最近のコンパイラのほとんどは、非標準のクールなことを可能にする一連の拡張をサポートしています。

于 2017-12-20T15:54:58.593 に答える
1

「goto found」式の結果はどうなるでしょうか? コンパイラもわからないので、?式の結果を判断できないため、エラーが発生します。

于 2012-06-30T09:19:57.607 に答える
1

一般に、?:オペレーターはクラシックの代わりにはなりませんif() ... else() ...。両方の演算子 (および条件) が値または値を返す式である場合は、そのまま使用できます。gotobreakまたはのようなステートメントでは使用できませんcontinue

次のことが可能です。

condition ? dothis() : dothat(); // there's no assignment, but it's still valid
var = condition ? dothis() : othervar;
condition ? (var=4, othervar=3) : (somevar = 1);

ただし、式以外のもの (つまり、値または結果を持たないもの) を含めることはできません。

condition ? continue : break; // statements letting the execution continue somewhere else
condition ? {var = 4; othervar = 3;} : dothat(); // trying to inline scopes/multiple exressions
var = condition ? while(var) {var--;} : 5; // similar, inlining a complete loop

これらの最後の例は実行できますが、if()呼び出すために本体を使用するか、関数本体を使用する必要があります。

if (condition) continue; else break;
condition ? (var = 4, var = 3) : dothat();
var = condition ? dotheloop(var) : 5; // ok, this could be 'var = condition ? 0 : 5;' but... example code
于 2012-06-30T09:30:33.737 に答える