演算子の優先順位
冒頭で述べた算数(初等教育での数学)での規則に加え、中等教育(日本の制度における高等学校などまでに相当)で使う演算子まで含め、ここでは説明する。なお、本来であれば2項演算子と単項演算子など、きちんと分類を考えて体系立った説明が必要だが、以下はそのようにはなっていない。
括弧内の項
冪乗と冪根
乗法と除法
加法と減法
これの意味するところは、例えばある数式の項の前後にそれぞれ異なる演算子があった場合、上記一覧の上の方(数字の若い方)にある演算子を先に適用すべきだということである。加法と乗法の交換法則および結合法則により、項の加算は任意の順序で可能であり、乗算も任意の順序で乗算可能だが、それらが混在している場合は標準の優先順位に従わなければならない。
除法を逆数による乗法として扱うことができ、減法を加法的逆元の加法として扱うことができる。すなわち、3 ÷ 4 = 3 • 1⁄4 である。言い換えれば、3を4で割った商は、3と 1⁄4 をかけた積と等しい。同様に 3 − 4 = 3 + (−4) であり、3と4の差は正の3と負の4の和と等しい。この理解により、 1 − 3 + 7 という式は1と負の3と7の和とみなすことができ、任意の順序で計算可能である。
C言語における演算子の優先順位にまつわるトピックとして、ビット演算や論理演算の優先順位が比較演算より低いという点がある。a == b && c == dのように、比較結果をさらに論理演算することは通常よくあるので妥当な設計と言えるが、ビット演算の優先順位の低さについては問題があり、例えば本来(x & mask) == yと書くべきところを誤ってx & mask == yと書いてしまうなど、しばしば言語仕様に関する理解度の低さやケアレスミスによるバグの原因となる。
デニス・リッチーは、この優先順位はC言語の仕様が変転していた黎明期(1970年代)において、B言語由来の仕様として、論理演算の演算子が分化していなかったことに原因があると説明している。具体的には、ビット演算と同じ記号列で、条件判定にまつわる式の文脈では論理演算の意味になる、という仕様であった。それにより例えば、
というように書かれたコードが既に複数の場所で大量に存在していた(具体的には "several hundred kilobytes of source code, and maybe 3 installations....")。そのため、&& と || を言語に追加した際に、それと同時に == と != の優先順位を下げる(下記の表で、現在の7から、10と11の間まで移動させる)ことで、既存のコードを壊してしまうことを恐れ(I had cold feet about the precedence problems.)そのようにはしなかった。結果として「ビット演算は必ず括弧で囲め」というイディオムで回避されているが、後から振り返ってみたならば、優先順位を変えていれば、そのようなイディオムは必要とならなかったのだし、そのほうが良かったのだろう、といったように述べている。