演算子の優先度

[戻る]
abc 2011/04/06(水) 12:02:16
int a,b;
a = 0;
b = a++;
printf("A:%d B:%d\n",a,b);
a = 0;
b = ++a;
printf("A:%d B:%d\n",a,b);

VS2005でコンパイル時の結果が
A:1 B:0
A:1 B:1
となります。
演算子の優先度からでは両方ともA:1 B:1になりそうなのですが…。

仲澤@失業者 2011/04/06(水) 12:48:34
優先順位の問題ではありません。
++、--演算子は、後置と前置では動作が異なります。
ヘルプを確認しましょう。

PATIO 2011/04/06(水) 13:02:52
もしも、C++言語の入門書で一通り勉強をしていないのであれば、
入門書で一通り勉強される事をお勧めします。
基本的な文法に関する知識は最低限必要です。
文法の部分の知識があった上での「習うより慣れろ」は良いと思いますけれど。

hirocco 2011/04/06(水) 13:36:30
優先度で言うと++のほうが高いんだけど,
インクリメント演算子/デクリメント演算子の元々の意味があるのでねぇ

前に書くと式を評価する前の演算で,後ろだと評価後に演算
b = a++;
は a を b に代入した後に,a に 1 を足すことになるのよ

a =2+a+++++a;
とかの a の答えとかわかりずらいけどねぇ

心配なら式を分けてしまえばいいですよ
a =a+1;
b =a;
なんてね,ほら

かっこよく知的なソースは,ドキドキするけど
見慣れないと確かによみずらい...
実際の話,勉強も大事だけど,何かを作り上げたいって気持ちが大事だから,
少々不恰好でもちゃんと理解して書くことが大事だよ
よくわかんないけど動いてるからいいや!なんてありえないからねぇ

あ,エラソウニゴメンナサイ

tenteku 2011/04/07(木) 09:43:07
優先順位ではないです。以下で動きを確認してみたら?

a = 0;
printf("A:%d\n",++a);
a = 0;
printf("A:%d\n",a++);

まだはじめたばかりなのだろうと思いますががんぱってください。

maru 2011/04/08(金) 09:15:23
> a =2+a+++++a;
> とかの a の答えとかわかりずらいけどねぇ
わかりずらい以前に未定義動作なんですけど。

tetrapod 2011/04/08(金) 09:29:12
未定義動作以前にコンパイルに絶対通らないんですけど。
これを無エラーで通すコンパイラが、もしあったら規格書違反。

hirocco 2011/04/08(金) 11:11:08
a =2 + a++ + ++a;
もちろんスペースは必要ですよ

a =a+1;
a =2+a+a;
a =a+1;
と同じ意味ですよね?

maru 2011/04/08(金) 11:41:32
> 未定義動作以前にコンパイルに絶対通らないんですけど。
確かに! 頭の中で勝手にスペースを入れてました。

> a =a+1;
> a =2+a+a;
> a =a+1;
> と同じ意味ですよね?
だから未定義だって言ってるでしょ。
http://www.kouno.jp/home/c_faq/c3.html#1

tetrapod 2011/04/08(金) 11:57:20
> と同じ意味ですよね?
うんにゃ違う。
言語仕様書的には未定義動作(誤ったプログラムであり結果は予測不能)

C : ISO/IEC 9899 6.5 Expressions
C++ : ISO/IEC 14882 5 Expressions 4

ひとつのオブジェクト(まあ端的にはひとつの変数と思ってよい)に対して、
副作用完了点と副作用完了点との間に、複数の副作用が作用すると、未定義動作。
> a =2 + a++ + ++a;
は a の値を変更しようとする副作用が3回発生している。
i=i++; も副作用2回が発生するので未定義動作。

正しいプログラムでも、副作用の発生順は未規定 (特に規定されている場合を除く)
未規定とは「正しいプログラムだけどその詳細を文書化しなくてよい」ということ。

> は a を b に代入した後に,a に 1 を足すことになるのよ
この文言が「順序」を解説しているのであれば、必ずしもそうではない。
1. b=a の古い値;
2. 新しい a の値=a の古い値+1;
の2つが行われることには間違いないが 1->2 の順か 2->1 の順かは未規定。
この例では、どの順でおきても問題ないが。

ありがちなコードとしては [全角] 文字を取り込もうとして
wchar_t wc=(getchar()<<8)|getchar(); // と書いたとき、
左側の getchar() が先に評価されるか、右側の getchar() が先に評価されるかは
コンパイラによっても、コンパイルオプションによっても、違いうる。

演算子の結合順(優先順)と、実演算順は無関係。

hirocco 2011/04/08(金) 11:59:26
へぇ,なるほどぉ
そうなんだぁ
勉強になります

古いスレッドには追加発言できません。