?:演算子はCでどのように機能しますか?


10

質問があります。コンパイラが次のコードでどのように動作するかです。

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

私は結果がある理由はわかりませんd = 11


1
なぜあなたはわからないのですか?他に何を期待し、その理由を教えてください。
ゲルハルト

2
関連する正確なセマンティクスを思い出しませんが、未定義の動作を観察している可能性があります。
chepner

3
いいえ、@ chepner、三項の条件を評価した後、選択した代替案を評価する前にシーケンスポイントがあります。それは私があなたが考えていると思うUBベクトルを避けます。
ジョンボリンジャー

ええ、コンパイラーに選択肢があると思ったところはわかりません。
chepner

回答:


6

int d = (b == c++) ? (c+1) : (c-1);

  • の値c++は、現在の値c11です。これとcは別に、12に増分されます。
  • b == 11b12 なのでfalse です。
  • (b == c++)は偽なので、(c-1)使用されます。また、cこの時点で12までの増分を完了する必要があります。
  • 以来c12は、c-111です。
  • d その値に初期化されます、11。

5

C標準に準拠(6.5.15条件演算子)

4最初のオペランドが評価されます。その評価と2番目または3番目のオペランド(評価される方)の評価の間にシーケンスポイントがあります。2番目のオペランドは、最初のオペランドが0と等しくない場合にのみ評価されます。3番目のオペランドは、最初のオペランドが0と等しい場合にのみ評価されます。結果は、2番目または3番目のオペランド(評価された方)の値であり、以下に説明する型に変換されます。110)

したがって、この宣言の初期化式では

int d = (b == c++) ? (c+1) : (c-1);

変数は、b変数の値と比較されるcポストインクリメントオペレータがそれをインクリメントする前に、そのオペランドの値を返すため。

値が互いに等しくない(b12にc設定され、11に設定されている)ため、部分式(c-1)が評価されます。

引用によると、オペレーターの状態の評価後にシーケンスポイントがあります。これは、状態の評価後cに値が12変数にポストインクリメント演算子を適用した後c。その結果、変数dは値112 - 1)によって初期化されます。


2
唯一の正解-この特定のケースは、でシーケンスポイントに言及することによって回答する必要があります?:。通常Cでは++、同じオペランドの他の演算と組み合わせることは未定義の動作であるためです。また、に?:はさまざまな特別なスノーフレークルールがあるため、このコードは予測どおりにしか機能しません。
ランディン

4

条件が偽のBeacuse、したがって、falseケースの処理が行われます。c-1しかし、あなたはインクリメント以降cでの状態でc++、そのためc今あります12。したがって、結果は11である12-1です。

編集:OPがポストインクリメントと誤解したのは、

だから実際に起こることはこのようなものです:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}

1
OPはc++、条件で与えられた操作の順序を参照していると思います。条件が偽であるが、その後orginalの値をc計算するために使用されているc - 1、いないインクリメントバージョン。
chepner

1
sincce 12 == 11 + 1それは本当だと思った...
J0S

しかし、新しいc値が使用されているのでそれは本当ではありませんか、それとも私はあなたのポイントを逃していますか?
エラクロン

私は間に誤解があるかもしれないと思うc++++c
ChatterOne

@ N00b c++ポストインクリメント演算子です。の値c++は11で、の副作用がありc == 12ます。++c12の値がなければなりません
chepner

4

通常のifステートメントに変換すると、コードは次のようになります。

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

ここでの手がかりは、条件がチェックされた後に cがインクリメントれることです。したがって、else状態に入りますが、cにはすでに値12があります。


1

三項演算子を参照してください

構文

状態 ?value_if_true:value_if_false

だから、あなたは書いた

int d = (b == c++) ? (c+1) : (c-1);

この状況では、ifチェックの後で 'c'値が増加し(c + 1 = 12)、その後 'd'値がc(12)-1として11に設定されるため、結果は11になります。

あなたが使用した場合、例えば:

int d = (b == ++c) ? (c+1) : (c-1);

「c」の値はステートメントをチェックする前に増加するため、trueとなり、「d」の値はc(12)+1、つまり13になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.