以下、2つのプログラムのうち、
例1)の結果がtrueになるのは理解できるのですが、
例2)の結果がfalseになるのが理解できません。。。。
例1)trueの場合
int i = 10;
boolean bo = (i++ == 10);
System.out.println("結果:" + bo);
↓
結果:true
例2)falseの場合
int i = 10;
boolean bo = (i++ == i++);
System.out.println("結果:" + bo);
↓
結果:false
当初、例2)のプログラムを作成した際は、
(i++ == i++)は、
インクリメントする前に演算が評価され、
そのあとにインクリメントされる想定でいました。
例2)のプログラムでは
どういった動きをするのかご教授お願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
Javaの場合限定、という前置きで。
Javaにおける前置インクリメント(++a)、後置インクリメント(a++)はどちらも式です。
厳密には前者は単項演算子の式、後者は後置式と呼ばれます。
式というものは、評価されて値を返します。変数の中身そのものではなく、我々には何等かの評価を行った後の値が見えます。
とっても古いですがJava言語規定というドキュメントがございまして、ここからそれぞれの式の仕様を引用します。
値1が変数の値に加えられ,合計は変数に格納される。
前置インクリメント式の値は,新しい値が格納された後の変数の値である。
とあります。
対して後置インクリメント演算子++では、
値1が変数の値に加えられ,合計は変数に格納される。
後置インクリメント式の値は,新しい値が格納される前の変数の値である。
と書かれています。
どちらも式を評価し、変数の中身が書き換わった後、評価結果として値を返しますが、前置のほうは新しく書き換わる前の値を返し、後置の場合は書き換わった後の値を返すという違いになります。
また、演算中における式は、カッコなどによる特別に順序の指定がなければ左から右へ順に評価されていきます。
なので、boolean bo = (i++ == i++);
がどのように評価されるかというと、まずカッコの中身が優先なので(i++ == i++)
が先に評価される。
わかりやすいように逆ポーランド記法風に書くと、i++ i++ ==
で、左から順に評価されていきます。
まず最初のi++
が評価されます。元のiは10なので、まず変数が演算されiが11になり、式の評価結果としては変数変更前の10が返ります。
次に、真ん中のi++
が評価されます。iの中身は11になっているので、変数が演算されると12になり、式の評価結果としては変更変更前の11が返ります。
最後に==
演算子が評価されます。2項演算子なので直前2つの値が一致するか評価されます。直前2つの値は式の評価後、10 11
となっているので一致せずfalseが返るというわけです。
このように、
- 式とは何なのか
- 評価と値の関係
- 各式の評価順序
を踏まえ、この件は未定義でも不定でもなく、規定の動作ということになります。
インクリメントの動作は行単位ではないのですよ!
なお、以下のサンプルプログラムで、インクリメント式の値がどんな値を返すのか、可視化できます。
実行してみてください。
java
1 public static void main(String []args){ 2 int a,b; 3 4 a = 10; 5 b = add(a++ , a++); 6 System.out.println("a=" + a); 7 System.out.println("b=" + b); 8 9 } 10 11 public static int add(int i1, int i2){ 12 System.out.println("i1=" + i1); 13 System.out.println("i2=" + i2); 14 return i1 + i2; 15 } 16 17/* 実行結果 18i1=10 19i2=11 20a=12 21b=21 22*/
投稿2018/09/26 13:54
総合スコア4447
0
未定義か?
Javaでは左から右へ順に評価することが保証されています。
15.7. Evaluation Order
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
引用元: Java Language Specification > Chapter 15. Expressions
本筋の回答
i++ == i++
について、例えばiが0のとき、次のように評価されます。
0. ==の左辺が評価され、評価値i(0)を返したあとインクリメントされiの値が1になる。
0. ==の右辺が評価され、評価値i(1)を返したあとインクリメントされiの値が2になる。
0. ==の両辺の評価値が比較される。
0. 当然 0 と 1 は等しくないので、falseが返される。
実験
Java
1int i = 0; 2int a, b; 3 4System.out.println( 5 (a = i++) == (b = i++) 6); 7System.out.println(a); 8System.out.println(b);
実行結果 Wandbox
false 0 1
投稿2018/09/26 13:19
編集2018/09/26 13:24総合スコア35660
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
こういうのは多くの言語で、未定義とか、不定とかです。
普通に考えられる実装では、片方のi
の値を求めて、インクリメントし、次に、他方のi
の値を求めて、インクリメントするという物です。つまり、10
と11
なので不一致です。
両辺のi
を求めてから、両辺ともインクリメントするような実装(この場合は真になる)も許容するために、どういう結果になるか分からないという言語仕様になっています。
「片方」「他方」という書き方をしましたが、二項演算子の左項と右項のどちらを先にに評価するかも、多くの言語では決まっていません。Javaがどうかは調べてませんが。
投稿2018/09/26 13:09
総合スコア84555
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/26 14:30