質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

1770閲覧

後置インクリメント同士の比較演算で悩んでいます

mer0

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/09/26 12:51

以下、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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

hope_mucci

総合スコア4447

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mer0

2018/09/26 14:30

ありがとうございます!!!! ものすごくわかりやすく説明頂いたおかげで、 すぐ理解できました! 単項演算子、後置式ともに すでに値を評価した上で、 変更前の値を返すか、後の値を返すかの 違いということだったんですね 逆ポーランド記法風という書き方があることも、 知れたので大変感謝です
guest

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
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こういうのは多くの言語で、未定義とか、不定とかです。
普通に考えられる実装では、片方のiの値を求めて、インクリメントし、次に、他方のiの値を求めて、インクリメントするという物です。つまり、1011なので不一致です。
両辺のiを求めてから、両辺ともインクリメントするような実装(この場合は真になる)も許容するために、どういう結果になるか分からないという言語仕様になっています。

「片方」「他方」という書き方をしましたが、二項演算子の左項と右項のどちらを先にに評価するかも、多くの言語では決まっていません。Javaがどうかは調べてませんが。

投稿2018/09/26 13:09

otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

i++ == i++

残念ながら、この式の動作は未定義となります
何が起ころうが不思議はない、ということですね

投稿2018/09/26 12:53

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mer0

2018/09/26 12:55

そうなんですか!? ご回答いただきありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問