1. ホーム
  2. c++

[解決済み] カンマ付きの三項演算子は、なぜ真の場合、1つの式しか評価しないのですか?

2022-08-29 02:55:53

質問

現在、C++ Primerという本でC++を勉強しているのですが、その中の練習問題のひとつに

次の式が何をするのか説明しなさい。 someValue ? ++x, ++y : --x, --y

何がわかっているのか?三項演算子はカンマ演算子よりも優先順位が高いということがわかりました。二項演算子の場合は非常にわかりやすかったのですが、三項演算子の場合は少し苦戦しています。二項演算子では、「優先順位が高い」ということは、「優先順位の高い式を括弧で囲んでも、実行は変わらない」ということです。

三項演算子の場合、私ならこうします。

(someValue ? ++x, ++y : --x, --y)

というように、同じコードになってしまい、コンパイラがどのようにコードをグループ化するかを理解するのに役立ちません。

しかし、C++コンパイラでテストした結果、この式がコンパイルされることは分かっています。 : 演算子がそれ自体で何を意味するのかわかりません。つまり、コンパイラーは三項演算子を正しく解釈しているようです。

次に、このプログラムを2通り実行してみました。

#include <iostream>

int main()
{
    bool someValue = true;
    int x = 10, y = 10;

    someValue ? ++x, ++y : --x, --y;

    std::cout << x << " " << y << std::endl;
    return 0;
}

の結果。

11 10

一方 someValue = false と表示されます。

9 9

なぜ C++ コンパイラは三項演算子の真の分岐に対して x をインクリメントし、三項演算子の偽分岐では xy ?

こんな感じで、true-branchを括弧で囲むところまでやってみました。

someValue ? (++x, ++y) : --x, --y;

のようになりますが、それでも結果的には 11 10 .

どのように解決するのですか?

として ラケテ が素晴らしい回答でおっしゃっているように、これは厄介なことです。少し補足しておきます。

三項演算子は、その形式を持たなければなりません。

論理式 ? : 割り当て式

ということで、以下のようなマッピングになります。

  • someValue : 論理式
  • ++x, ++y : 表現
  • 割り当て式 --x, --y または --x ?

実はこれだけです。 --x というのは 代入式 はコンマで区切られた二つの式として解析することができないため(C++の文法規則によれば)。 --x, --y として扱うことはできません。 代入式 .

その結果、3項(条件)式の部分は次のようになります。

someValue?++x,++y:--x

を考慮することは、読みやすさのために役立つかもしれません。 ++x,++y を計算された として 括弧付き (++x,++y) の間に含まれるものはすべて ?: の順になります。 の後に の後に続きます。(記事の続きは括弧で囲みます)。

という順に評価されます。

  1. someValue?
  2. (++x,++y) または --x (に応じて bool の結果による)

この式は、コンマ演算子に対する左の部分式として扱われ、右の部分式は --y のようになります。

(someValue?(++x,++y):--x), --y;

ということは、左側は 捨て値の式 であり、それは間違いなく評価されるが、その後、右辺を評価してそれを返すという意味である。

では、次のような場合はどうなるのでしょうか。 someValuetrue ?

  1. (someValue?(++x,++y):--x) が実行され、インクリメントされます。 xy であることを 11 であり 11
  2. 左の式は捨てられます(ただし、インクリメントの副作用は残ります)。
  3. カンマ演算子の右辺を評価する。 --y を評価し、デクリメントします。 y に戻り 10

この挙動を修正するには、グループ化することができます。 --x, --y を括弧で囲むと 一次式 どの の有効なエントリです。 の有効なエントリです。 *:

someValue?++x,++y:(--x, --y);


*をつなぐ、ちょっと面白いロングチェーンです。 割り当て式 を一次式に戻す、ちょっとおかしな長い鎖です。

代入式 ---(構成することができる)--> 条件式 --> 論理式 --> 論理式 --> 包括的-論理式 --> 排他的論理和 --> と式 --> 等式 --> 関係式 --> シフト式 --> 加算式 --> 乗法的表現 --> pm-式 --> キャスト式 --> 単項式 --> postfix-式 --> 一次式