CとC++の演算子

CとC++の演算子（シーとシープラスプラスのえんざんし）はC++とC言語における演算子の一覧である。C++に存在するすべての演算子を掲示し、さらにCにも存在するかどうかを示している。なお、Cでは演算子の多重定義は不可能である。

&&、||、?:（条件演算子）ならびに,（コンマ演算子）はを形成する。ただし、多重定義されていない場合に限る。

これらのうち、Cにも存在するものは、コンマ演算子と矢印演算子を除いて、Java、Perl、C#、PHPにも同じ優先順位・結合性を持って存在する。ただし、PHPの条件演算子は例外的に左から右への結合である。

演算子の表 
この表においてa, b, cは有効な値 (リテラル・値・変数・戻り値)・オブジェクト名・左辺値を適宜意味する。なお、「多重定義可能か」はC++での話である。

演算子の優先順位 
以下の表は、C++とCにおける優先順位と結合性を示したものである（なお、Java, Perl, PHPなど最近の言語の多くは同様の優先順位を持つ）。演算子は優先順位の低いものほど下のほうに掲載されている。同じセルに掲載されている演算子同士は同じ優先度を持つ。なお、たとえ多重定義しても、演算子の優先順位は変化しない。

CやC++において、演算子の構文は文脈自由文法にて定義されている。この表は、その構文より導き出されるものである。

この表では、正確に表現できていない部分が一部に存在する。たとえば、条件演算子は、代入やコンマ演算子より高い優先度を持つものの、中央のオペランドではそれらを含むすべての演算子の使用が可能である。すなわち、a ? b , c : dはa ? (b, c) : dと解釈される。また、(a ? b), (c : d)は意味を成さず、コンパイルエラーとなる。なお、括弧で囲われていない型変換式の結果はsizeofの対象となれない。つまり、sizeof (int) * xは(sizeof(int)) * xの意味となりsizeof ((int) * x)とはならない。

補足 
優先順位の表は、括弧で括られていない式において結びつく順序を決める。
 ++x * 3は優先順位の規則がなければ曖昧である。しかし、実際には、優先順位によってxは*より++に結びつくので、(++x) * 3と解釈される。
 同様に、3 * x++ではxのみがインクリメントの対象となる。
 優先順位と結合性の問題はのように一般化できる。コンパイラの目標はこのようなダイアグラムを式として解決することである。この図は各単項の演算子（ここではそれぞれ3 + ( . ), 2 * ( . ), ( . )++, ( . )[i]と表記する）がyへ結合しようとしていることを表す。優先順位の表から、各部分式は最終的に、( . )[i]はyへ、( . )++はy[i]へ、2 * ( . )は(y[i])++へ、3 + ( . )は2 * ((y[i])++)という結合にしか成り得ないことが決定される。
 注意: 優先順位からは部分式が「何」に対して作用するかを決めるが、「いつ」作用するかには関与しない。上の2 * ((y[i])++)という例では、優先順位と直接には関係なく、単に演算のためにその値が必要であるという（データフロー的な）理由により、後置++演算子がy[i]より後に作用する、ということしか明確ではない。

CやC++において、演算子の結合は、優先順位ではなく（各々の標準規格での）文法によって定められている。このため、僅かな差異が生じる場合がある。たとえば、Cの条件演算子は以下のように定義されている。
logical-OR-expression ? expression : conditional-expression
一方、C++では次のように定義されている。
logical-or-expression ? expression : assignment-expression
そのため、
e = a ? b : c = d
という式は、Cだと
e = ((a ? b : c) = d)
と解釈されて条件演算子の結果が左辺値でないことによるエラーとなるが、C++だと
e = (a ? b : (c = d))
と解釈され、正しい式となる。

論理演算子の優先順位は問題があると指摘されている。概念的には&と|は算術演算子の+と-のような存在である。しかし、a + b == 7は(a + b) == 7と解釈されるが、a & b == 7という式はa & (b == 7)と解析されてしまう。ほかにも期待通りに解釈させるための括弧を必要とする場合がある。

C++の演算子の代替表現 
C++では、一部の演算子に対して、全く同じに機能する代替表現を予約している。代替表現はキーワードと同様に予約されている字句として扱われる。

これらの代替表現は、記号的に等価として扱われ、どこでも記号を代替表現に置き換えても問題ない。置き換える先は、演算子としてではなく記号として扱われる。つまりbitandはビット積演算子だけでなくアドレス取得演算子の代わりに用いても機能するということである。

ANSI Cでは、これらを<iso646.h>でCプリプロセッサのマクロを用いて定義している。これとの互換性のために、C++ではヘッダ<iso646.h>と<ciso646>を用意しているが、中身は空である。

C++では、すべての比較演算子は真偽値を返す。
bool a;
int b = 1;
int c = 2;
a = b == c;
==はbool型の値を返すため、==演算子はif文などの中に限定されず、どこでも使用可能である。なお、a = b == c;は次のように書くのと同様の効果をもたらす。
bool a;
int b = intに変換できる任意の値;
int c = もう一つの任意値;
if (b == c)
    a = true;
else
    a = false;

脚注

関連項目 
 キーワード (C言語)
 キーワード (C++)

C言語
C++