- PR -

演算子の優先順位について

投稿者投稿内容
m.i
会議室デビュー日: 2008/10/06
投稿数: 9
投稿日時: 2008-10-16 17:58
以下のようなプログラムがあるとします。
public class IfTest {
public static void main(String[] args) {
if(false && false | doStuff()) {
System.out.println("true");
}
}
static boolean doStuff(){
System.out.println("doStuff() exec");
return true;
}
}
この場合、演算子の優先順位から考えると、以下の順番にて実行されると
想定しておりました。
1.
&&演算子よりも|演算子の方が優先順位が高いので
false | doStuff()が実行され結果trueなる。
また、doStuff() execという文字列も出力される。
2.
false &&と1.の結果である、trueを比較するべきであるが
左側のオペランドがfalseであり且つ演算子が&&であるので
右側のtrueとの比較は行わない。

しかし、実際はfalse &&の部分が先に評価されfalse | doStuff()部分は
実行されませんでした。
演算子の優先順位と挙動とが一致しないように思われるのですが、
皆さんどのように解釈すべきでしょうか。
ご指摘頂ければ幸いです。
以上宜しくお願い致します。
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2008-10-16 18:38
さっきまでの投稿は、ウソばかり書いていたので削除しました。m(_ _;m

原因は、&&と||が、ショートサーキット演算子と呼ばれる所以なんですね。
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-10-16 19:10
Java 言語仕様の 15.7.2 項や、15.23 項を読んでみるといいかも。
http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html

版が違いますが、↑を和訳したもの。
http://www.y-adagio.com/public/standards/tr_javalang/15.doc.htm

※和訳のほうだと、それぞれ 15.6.2 項、15.22 項に記述されてますね。

[ メッセージ編集済み 編集者: rain 編集日時 2008-10-17 10:09 ]
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2008-10-16 19:13
「|」じゃなくて「||」だと思いますが、
doStuff()は呼ばれるはずですよ。実行して確認しました。

実際は「||」より「&&」の方が優先順位は高うございます。
ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-10-17 02:10
コード:

System.out.println("flse && false | doFunc() is " + (false && false | e.doFunc("1")));
System.out.println("flse ^ false | doFunc() is " + (false ^ false | e.doFunc("2")));
System.out.println("flse || false | doFunc() is " + (false || false | e.doFunc("3")));
System.out.println("flse & false | doFunc() is " + (false & false | e.doFunc("4")));
System.out.println("flse | false | doFunc() is " + (false | false | e.doFunc("5")));




うーむ・・・

バグじゃないですか?

コード:

結果:(Java1.5/Eclipse3.2)
flse && false | doFunc() is false
doFunc:2
flse ^ false | doFunc() is true
doFunc:3
flse || false | doFunc() is true
doFunc:4
flse & false | doFunc() is true
doFunc:5
flse | false | doFunc() is true


if (false && false | e.doFunc("1")) {
System.out.println("OK" + 1);

}
if (false ^ false | e.doFunc("2")) {
System.out.println("OK" + 2);

}
if (false || false | e.doFunc("3")) {
System.out.println("OK" + 3);

}
if (false & false | e.doFunc("4")) {
System.out.println("OK" + 4);

}
if (false | false | e.doFunc("5")) {
System.out.println("OK" + 5);

}

doFunc(String s) {
System.out.println("doFunc" + s);
return true;
}




C# 2008
コード:

class Test
{
public Test()
{
Console.WriteLine("false && false | doFunc('1') is {0}", false && false | doFunc("1"));
}
private bool doFunc(string s)
{
Console.WriteLine("doFunc:OK");
return true;
}
}




Java と同じ結果、ってことは正しい文法解釈であるわけで・・・
お互いに薄っぺらな知識ってことでm(__)m



[ メッセージ編集済み 編集者: ぴあちゃん 編集日時 2008-10-17 02:18 ]
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2008-10-17 09:48
引用:

スフレさんの書き込み (2008-10-16 19:13) より:
「|」じゃなくて「||」だと思いますが、


「|」もあり得ます。
引用:

doStuff()は呼ばれるはずですよ。実行して確認しました。


「|」を「||」に書き換えた場合、スフレ氏の指摘の通りになります。
引用:

実際は「||」より「&&」の方が優先順位は高うございます。


「|」の優先順位は、さらに高いです。

今回の場合、優先順位というよりも、結合順位と表現した方がしっくりくるかも。
演算子自身の順位は評価されても、演算そのものは行われないんですね。
ただし、「||」と「&&」の左項がそれぞれtrue、falseの場合。

あるいは、全部承知の上での指摘であって、私のものは的外れでしょうか。
その場合は、ご指摘いただけたらありがたいです。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2008-10-17 09:53
おー、boolean に「|」って使えたんですね。知りませんでした。
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-10-17 10:27
引用:

ぴあちゃんさんの書き込み (2008-10-17 02:10) より:
コード:
System.out.println("flse && false | doFunc() is " + (false && false | e.doFunc("1")));
System.out.println("flse ^ false | doFunc() is " + (false ^ false | e.doFunc("2")));
System.out.println("flse || false | doFunc() is " + (false || false | e.doFunc("3")));
System.out.println("flse & false | doFunc() is " + (false & false | e.doFunc("4")));
System.out.println("flse | false | doFunc() is " + (false | false | e.doFunc("5")));





言語仕様をもとに解釈してみました。

コード:
false && false | e.doFunc("1")


式の中に && があるため、先に && の左辺が評価されます。
&& の左辺が false であるため、右辺は評価も実行もされず、式全体の結果が false になります。

コード:
false ^ false | e.doFunc("2")


式を評価する前に、e.doFunc() の実行が行われます。
false ^ false = false, false | true = true であるため、式全体の結果は true になります。

コード:
false || false | e.doFunc("3")


式の中に || があるため、先に || の左辺が評価されます。
|| の左辺が false であるため、次に || の右辺が評価されます。
|| の右辺を評価する前に、e.doFunc() の実行が行われます。
false | true = true であるため、式全体の結果は true になります。

コード:
false & false | e.doFunc("4")


式を評価する前に、e.doFunc() の実行が行われます。
false & false = false, false | true = true であるため、式全体の結果は true になります。

コード:
false | false | e.doFunc("5")


式を評価する前に、e.doFunc() の実行が行われます。
false | false = false, false | true = true であるため、式全体の結果は true になります。

スキルアップ/キャリアアップ(JOB@IT)