[解決済み] カンマ付きの三項演算子は、なぜ真の場合、1つの式しか評価しないのですか?
質問
現在、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
をインクリメントし、三項演算子の偽分岐では
x
と
y
?
こんな感じで、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)
の間に含まれるものはすべて
?
と
:
の順になります。
の後に
の後に続きます。(記事の続きは括弧で囲みます)。
という順に評価されます。
-
someValue?
-
(++x,++y)
または--x
(に応じてbool
の結果による)
この式は、コンマ演算子に対する左の部分式として扱われ、右の部分式は
--y
のようになります。
(someValue?(++x,++y):--x), --y;
ということは、左側は 捨て値の式 であり、それは間違いなく評価されるが、その後、右辺を評価してそれを返すという意味である。
では、次のような場合はどうなるのでしょうか。
someValue
は
true
?
-
(someValue?(++x,++y):--x)
が実行され、インクリメントされます。x
とy
であることを11
であり11
- 左の式は捨てられます(ただし、インクリメントの副作用は残ります)。
-
カンマ演算子の右辺を評価する。
--y
を評価し、デクリメントします。y
に戻り10
この挙動を修正するには、グループ化することができます。
--x, --y
を括弧で囲むと
一次式
どの
は
の有効なエントリです。
の有効なエントリです。
*:
someValue?++x,++y:(--x, --y);
*をつなぐ、ちょっと面白いロングチェーンです。 割り当て式 を一次式に戻す、ちょっとおかしな長い鎖です。
代入式 ---(構成することができる)--> 条件式 --> 論理式 --> 論理式 --> 包括的-論理式 --> 排他的論理和 --> と式 --> 等式 --> 関係式 --> シフト式 --> 加算式 --> 乗法的表現 --> pm-式 --> キャスト式 --> 単項式 --> postfix-式 --> 一次式
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] C++の規格では、初期化されていないboolがプログラムをクラッシュさせることは可能ですか?
-
[解決済み] not(True) in [False, True]」はなぜFalseを返すのですか?
-
[解決済み】C言語の三項演算子に相当するGoの慣用句は何ですか?
-
[解決済み】STLスタイルのイテレータを実装し、よくある落とし穴を回避する方法は?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された