- 追加された行はこの色です。
- 削除された行はこの色です。
演算子の優先順位について
C・C++における演算子の優先順位について
迷ったら()をつける!
優先順位の表
|演算子|名称等|結合規則|
|演算子|名称等|結合規則|h
|::|スコープ解決(名前空間、C++のみ)|→|
|() [] -> . ++ -- typeid 各種キャスト|関数,添字,メンバ選択,後置増分減分,型情報,○○_castの形のキャスト|→|
|++ -- ~ ! + - * & new delete sizeof ()|前置増分減分,補数,否定,ポインタ参照,アドレス取得,オブジェクト生成,オブジェクト破棄,サイズ取得,キャスト|←|
|++ -- ~ ! + - * & new delete sizeof ()|前置増分(インクリメント)減分(デクリメント),補数,否定,ポインタ参照,アドレス取得,オブジェクト生成,オブジェクト破棄,サイズ取得,キャスト|←|
|* / % |乗算,除算,剰余|→|
|+ -|加算,減算|→|
|<< >>|左シフト,右シフト|→|
|< <= > >=|不等号|→|
|== !=|等号|→|
|< <= > >=|比較|→|
|== !=|等価|→|
|&|AND|→|
|^|EX-OR|→|
|||OR|→|
|&&|論理AND|→|
||||論理OR|→|
|?:|条件|←|
|?:|条件(三項)|←|
|= *= /= %= += -= <<= >>= &= |= ^=|代入|←|
|,|カンマ|→|
結合規則 →:左から右 ←:右から左
上のものほど優先順位が高い
・優先順位とは
いくつかの演算子がひとつの文中で使用されている場合、優先順位の高いものから順に実行される
例えば*(乗法)は+(加法)より優先順位が高いため
a+b*c
はまずb*cが実行されたのちその結果とaを足す
・結合規則とは
結合規則とは多数並んでいる場合に実行される順番のこと
例えば=(代入)の結合規則は右から左であるので
a=b=c
は
a=(b=c)
と解釈される。つまりaにもbにもcが代入される
~
少し話がそれるが、整数(=整数型 intとかcharとか)/整数の結果は整数で返る
例えばa=2/3とすればaには0が入る
実数(=浮動小数点型 doubleとか)/整数 あるいは 整数/実数 そして当然 実数/実数 は実数が返る
ここでも結合規則について注意すべき場合がある
次の例を見てみよう(60°の弧度法表示を求めるプログラム)
#code(cpp){{
int a,b;
double d;
a=2;
b=3;
d=3.14;
printf("2/3*3.14=%f\n",1/b*a*d);
printf("2/3*3.14=%f\n",a/b*d);
printf("2/3*3.14=%f\n",a*d/b);
printf("2/3*3.14=%f\n",d*a/b);
}}
さて、上記のプログラムを実行するとどうなるだろう
自分達が普段している計算ではすべて同じはずである。しかしプログラムではそうも行かない
上のプログラムははじめの二つが0を出力し、あとの二つが望む結果を返す
*と/は優先順位が等しく、結合法則が左から右のためである
つまりa/b*dはまずa/bを計算し、それにdを掛ける
前述の通りa/bは整数/整数なので結果は整数。従って0が返ってくる。それにdを掛けても0である(厳密にはdを掛けた後の0は浮動小数点型なので0.0と書いたほうが良いかもしれない)
~
・&&と||
&&と&、||と|これらの違いに関して述べる
少々無理やりな例だが、次のようなプログラムを考えてみる
#code(cpp){{
int input;
int ans2,ans3;
scanf("%d",&input);
printf("The input value ");
if((ans2=input%2)==0 || (ans3=input%3)==0){
printf("is a multiple of ");
if(ans2==0)printf("2.\n");
if(ans3==0)printf("3.\n");
}else{
printf("is not a multiple of 2 and is not a multiple of 3.\n");
}
}}
このプログラムは意図した通りには動かない
||は論理ORであるためである
式1 || 式2
の形があった場合、もし式1が真であれば式2は評価されない
しなくても条件が真であることが分かっているためである
つまり上記のプログラムではinputが2の倍数ならばans3の計算や代入は行われない
&&についても同様で
式1 && 式2
の形があった場合、もし式1が偽であれば式2は評価されない
|や&はビットごとの演算なので
式1 | 式2 や 式1 & 式2
の形でも式1も式2も必ず実行される
上記のプログラムも||を|に変えれば正しく動く
では||や&&より|や&を使った方がよいのだろうか?
無論そんなことはなく一般には||や&&を使った方がよいだろう
評価をしないのはしなくても結果が分かっているからである
そのほうが速いのは言うまでもない
なお、||や&&は比較や等号よりは優先順位が低いが、代入よりは高いので注意
というか代入の優先順位がかなり低い
a = b > c
はb>cの結果をaに代入しようとするし
a/=2 || b/=2
これはコンパイルすら通らない
a /= (2||b) /= 2
こう解釈されるためである