演算子の優先度と副作用について
C言語はかなり長い間お付き合いをしているが,演算子の優先度と副作用あたらりがどうやら怪しいらしい.
ポインタ並に難しいのではないかと思う,今日この頃です.
とりあえず,簡単に自分的まとめ
演算子の優先度
演算子 | 結合規則 |
---|---|
() [] -> . ++ --(後置) | 左から右 |
! ~ ++ --(前置) + -(符号) * &(アドレス) (type) sizeof | 右から左 |
* / % | 左から右 |
+ - | 左から右 |
<< >> | 左から右 |
< <= > >= | 左から右 |
== != | 左から右 |
& | 左から右 |
^ | 左から右 |
| | 左から右 |
&& | 左から右 |
|| | 左から右 |
? : | 右から左 |
= += -= *= /= %= &= ^= |= <<= >>= | 右から左 |
, | 左から右 |
この表は覚えておいて損はないのですが・・・一つ疑問.
後置演算子が優先度高いってどういうことなんだ?
int i = 0,sum; sum = i++;
とかあった場合,どの段階でiの値が増加するかと言うと,;が来る前までに増加します.
つまり,sumには増加するまえのiの値が入り,その後にiが1増えるという.
・・・なんか表を見てると納得いかない.
ちなみに前置演算子の場合は
int i=0, sum; sum = ++i;
だと,iの値が増加してからsumに代入されます.
これは,納得なんですよね.
だって,前置演算子の方が表を見る限りでは優先度が高いですからね.
これはどうなるのでしょうか?
int i = 0, a[3]; a[i] = i++;
私の環境では,a[0]にiの値が入ってから,iが1増加しました.
ちなみに,コンパイラによって動作は変わります.
つまり,iの値が増加してから,a[1]に値が入る場合があるかもしれないということです.
前置・後置演算子は副作用を発生させやすいのです.(う〜ん,難しくなってきた)
次の場合のsumの値はどうなるのでしょうか?
int sum, i =0; sum = ++i * ++i * ++i;
私の環境では,「12」でした.
おそらく,左と真ん中の「++i」が1づつ増えてから掛け合わされて,右の「++i」が1増えてから左と掛け合わされたものかと・・・.(何言ってるのかさっぱりになってきた)
ちなみに,これもコンパイラによって結果が変わります.
今まで演算子の優先順位と副作用についてかるーく説明しましたが,ここで重要なポイント!
優先順位と結合規則によって式の意味はきまります.
しかし,どういう順番で計算されるかは,わかりません!!
なんじゃそりゃ!!!
優先順位と結合規則はあくまで「目安」であって,計算はその値になるように適当にやられてるっぽいです.
(ある意味すごいのかも?)
・・・C言語恐るべし