三項演算子の仕様

アバター
いわん
記事: 32
登録日時: 9年前

三項演算子の仕様

投稿記事 by いわん » 9年前

簡易スクリプト言語開発スピンオフ企画第2弾で式入力計算ソフト製作中・・・
三項演算子(?:)でつまずいた。

true?1,2:3,4
自作ソフトの今の仕様では上の式はエラーになる。
,演算子は優先順位は低いので三項演算子が途中で分断されてエラーでよいと思ってたけど、
C++でコンパイルしたらエラーにならなかった。
true?(1,2):3,4
ということになるらしい。真式内の,は考慮されない?でも偽式の後ろの,はどういうことになるんだろう?
混乱してきた。
画像

アバター
へろりくしょん
記事: 92
登録日時: 14年前

Re: 三項演算子の仕様

投稿記事 by へろりくしょん » 9年前

コンマ演算子は、左オペランドを評価した後右オペランドを評価します。
この際、左オペランドの評価した値は読み捨てられます。

また、左オペランドの評価が終わった瞬間に副作用完了しますので、
コンマ演算子が取る値は右オペランドの値となります。


今回の例では

true ? 2 : 4
false ? 2 : 4

とするのと同じです。

YuO
記事: 947
登録日時: 14年前

RE: 三項演算子の仕様

投稿記事 by YuO » 9年前

C++の関連するところを仕様書 (INCITS/ISO/IEC 14882:2011) から抜き出すと,

CODE:

(6.2 Expression statement)
expression-statement: 
    expression(opt) ';'

(5.18 Comma operator)
experssion:
    assignment-expression
    expression ',' assignment-expression

(5.17 Assignment and compound assignment operators)
assignment-expression:
    conditional-expression
    logical-or-expression assignment-operator initializer-clause
    throw-expression
assignment-operator: one of
    '=' '*=' '/=' '%=' '+=' '-=' '>>=' '<<=' '&=' '^=' '|='

(5.16 Conditional operator)
conditional-operator:
    logical-or-expression
    logical-or-expression '?' expression ':' assignment-expression
となります。
オフトピック
行頭に括弧の行は,筆者註で仕様書の節等の番号,
'と'で囲っている物はサンセリフ体,(と)で囲っている物は原文下付きセリフ斜体,
one ofはセリフ体,それ以外はセリフ斜体。
なので,
true ? 1 , 2 : 3 , 4
は,これが式文の式であると仮定した場合,理論上は

CODE:

expression: "true ? 1 , 2 : 3 , 4"
    expression: "true ? 1 , 2 : 3"
        assignment-expression: "true ? 1 , 2 : 3"
            conditiona-operator: "true ? 1 , 2 : 3"
                logical-or-expression: "true"
                    ... literal: "true"
                '?'
                expression: "1 , 2"
                    expression: "1"
                        assignment-expression: "1"
                            conditional-exprssion: "1"
                                logical-or-expression: "1"
                                    ... literal: "1"
                    ','
                    assignment-expression: "2"
                        conditiona-expression: "2"
                            logical-or-expression: "2"
                                ... literal: "2"
                ':'
                assignment-expression: "3"
                    conditiona-expression: "3"
                        logical-or-expression: "3"
                            ... literal: "3"
    ','
    assignment-expression: "4"
        conditional-expression: "4"
            logical-or-expression: "4"
            ... literal: "4"
と構文解析されます。
# 面倒なのでlogical-or-expressionからliteralまでとliteralの定義は省略。

つまり,全体としては(条件演算子), 4というコンマ演算子の形式を持つ式であるため,式の値は常に4になります。

アバター
みけCAT
記事: 6734
登録日時: 14年前

RE: 三項演算子の仕様

投稿記事 by みけCAT » 9年前

C++の規格書(に近似できるドキュメント)を読みましょう。
N3337 5.16 Conditional operator さんが書きました: conditional-expression:
[tab=30]logical-or-expression
[tab=30]logical-or-expression ? expression : assignment-expression
N3337 5.18 Comma operator さんが書きました: expression:
[tab=30]assignment-expression
[tab=30]expression , assignment-expression
expressionは文(N3337 6.2 Expression statement)や条件式(6.4 Selection statements、6.5 Iteration statements)として使える「式」を表します。
assignment-expressionはそのまま三項演算子(conditional-expression)になったり、代入演算子やthrowになったりできます。
conditional-expressionは三項演算子です。
logical-or-expressionは論理OR(||)演算子ですが、さらに優先順位の高い演算子やprimary-expression、リテラル、識別子などに置き換えることができます。

この文法から、三項演算子の一番左や一番右のオペランドにコンマ演算子を使うことはできないが、真ん中のオペランドにはコンマ演算子を使うことができることがわかります。
(ただし、primary-expressionの中に丸括弧で囲んだexpressionがあるので、丸括弧で囲んだ中ではコンマ演算子を使うことができます)

したがって、 true?1,2:3,4 という式は、真ん中のコンマ演算子は三項演算子のオペランドに入っているが、後ろのコンマ演算子は三項演算子に入っていないことがわかります。
すなわち、この式を文法にそって分解すると

CODE:

expression : true?1,2:3,4
    expression : true?1,2:3
        assignment-expression -> conditional-expression : true?1,2:3
            logical-or-expression -> literal : true
            ?
            expression : 1,2
                expression : 1
                    assignment-expression -> conditional-expression : 1
                        logical-or-expression -> literal : 1
                ,
                assignment-expression -> conditional-expression : 2
                    logical-or-expression -> literal : 2
            :
            assignment-expression -> conditional-expression : 3
                logical-or-expression -> literal : 3
    ,
    assignment-expression -> conditional-expression : 4
        logical-or-expression -> literal : 4
となり、この式は (true ? (1 , 2) : 3) , 4 と解釈できるということがわかります。

従って、自作ソフトの仕様は自由ですが、C++においては今回の例は 4 とするのと同じであり、
へろりくしょん さんが書きました:今回の例では

true ? 2 : 4
false ? 2 : 4

とするのと同じです。
という主張は誤りです。

アバター
いわん
記事: 32
登録日時: 9年前

Re: 三項演算子の仕様

投稿記事 by いわん » 9年前

みなさん、情報ありがとうございました。
あまり言語仕様の勉強をしないで結果オーライでやってるものだからいざというときボロが出ますね^^;
まぁ、自分で作っているものだから仕様は勝手に決めてもいいわけですが、なるたけメジャーな言語仕様に合わせていこうと思っています。