This is a list of operators in the C and C++ programming languages.

All listed operators are in C++ and lacking indication otherwise, in C as well. Some tables include a "In C" column that indicates whether an operator is also in C. Note that C does not support operator overloading.

When not overloaded, for the operators <code>&&</code>, <code>||</code>, and <code>,</code> (the comma operator), there is a sequence point after the evaluation of the first operand.

Most of the operators available in C and C++ are also available in other C-family languages such as C#, D, Java, Perl, and PHP with the same precedence, associativity, and semantics.

Many operators specified by a sequence of symbols are commonly referred to by a name that consists of the name of each symbol. For example, <code>+=</code> and <code>-=</code> are often called "plus equal(s)" and "minus equal(s)", instead of the more verbose "assignment by addition" and "assignment by subtraction".

Operators

In the following tables, lower case letters such as <code>a</code> and <code>b</code> represent literal values, object/variable names, or l-values, as appropriate. <code>R</code>, <code>S</code> and <code>T</code> stand for a data type, and <code>K</code> for a class or enumeration type. Some operators have alternative spellings using digraphs and trigraphs or operator synonyms.

Arithmetic

C and C++ have the same arithmetic operators and all can be overloaded in C++.

{| class="wikitable" style="width:100%"

! colspan="2" rowspan="2" | Operation

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

| colspan="2" | Addition

| align="center" |

|

|

|-

| colspan="2" | Subtraction

| align="center" | <code>a - b</code>

|

|

|-

| colspan="2" | Unary plus; integer promotion

|align="center" | <code>+a</code>

|

|

|-

| colspan="2" | Unary minus; additive inverse

| align="center" | <code>-a</code>

|

|

|-

| colspan="2" | Multiplication

| align="center" | <code>a * b</code>

|

|

|-

| colspan="2" | Division

| align="center" | <code>a / b</code>

|

|

|-

| colspan="2" | Modulo

{| class="wikitable" style="width:100%"

! colspan="2" rowspan="2" | Operation

! rowspan="2" | Syntax

! rowspan="2" | In C

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

| colspan="2" | Equal to

| align="center" | <code>a == b</code>

|

|

|

|-

| colspan="2" | Not equal to

| style="text-align:center;" | <code>a != b</code> ||

|

|

|-

| colspan="2" | Greater than

| style="text-align:center;" | <code>a > b</code> ||

|

|

|-

| colspan="2" | Less than

| style="text-align:center;" | <code>a < b</code> ||

|

|

|-

| colspan="2" | Greater than or equal to

| style="text-align:center;" | <code>a >= b</code> ||

|

|

|-

| colspan="2" | Less than or equal to

| style="text-align:center;" | <code>a <= b</code> ||

|

|

|-

| colspan="2" | Three-way comparison

{| class="wikitable" style="width:100%"

! colspan="2" rowspan="2" | Operation

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

| colspan="2" | NOT

| align="center" | <code>!a</code>

|

|

|-

| colspan="2" | AND

| style="text-align:center;" | <code>a && b</code>

|

|

|-

| colspan="2" | OR

| style="text-align:center;" | <code>a <nowiki>||</nowiki> b</code>

|

|

|}

Bitwise

C and C++ have the same bitwise operators and all can be overloaded in C++.

{| class="wikitable" style="width:100%"

! colspan="2" rowspan="2" | Operation

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

| colspan="2" | NOT

| align="center" | <code>~a</code><br/>

|

|

|-

| colspan="2" | AND

| style="text-align:center;" | <code>a & b</code>

|

|

|-

| colspan="2" | OR

| style="text-align:center;" | <code>a <nowiki>|</nowiki> b</code>

|

|

|-

| colspan="2" | XOR

| style="text-align:center;" | <code>a ^ b</code>

|

|

|-

| colspan="2" | Shift left use an arithmetic shift (i.e., sign extension), but a logical shift is possible.

| style="text-align:center;" | <code>a >> b</code>

|

|

|}

Assignment

C and C++ have the same assignment operators and all can be overloaded in C++.

For the combination operators, <code>a ⊚= b</code> (where <code>⊚</code> represents an operation) is equivalent to <code>a = a ⊚ b</code>, except that <code>a</code> is evaluated only once.

{| class="wikitable" style="width:100%"

! rowspan="2" | Operation

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

! | Assignment

| style="text-align:center;" |

|

|

|-

! | Addition combination

| align="center" | <code>a += b</code>

|

|

|-

! | Subtraction combination

| style="text-align:center;" | <code>a -= b</code>

|

|

|-

! | Multiplication combination

| style="text-align:center;" | <code>a *= b</code>

|

|

|-

! | Division combination

| style="text-align:center;" | <code>a /= b</code>

|

|

|-

! | Modulo combination

| style="text-align:center;" | <code>a %= b</code>

|

|

|-

! | Bitwise AND combination

| style="text-align:center;" | <code>a &= b</code>

|

|

|-

! | Bitwise OR combination

| style="text-align:center;" | <code>a <nowiki>|</nowiki>= b</code>

|

|

|-

! | Bitwise XOR combination

| style="text-align:center;" | <code>a ^= b</code>

|

|

|-

! | Bitwise left shift combination

| style="text-align:center;" | <code>a <<= b</code>

|

|

|-

! | Bitwise right shift combination

| style="text-align:center;" | <code>a >>= b</code>

|

|

|}

Member and pointer

{| class="wikitable" style="width:100%"

! colspan="2" rowspan="2" | Operation

! rowspan="2" | Syntax

! rowspan="2" | Can overload

! rowspan="2" | In C

! colspan="2" | C++ prototype

|-

! in class K

! outside class

|-

| colspan="2" | Subscript

| align="center" | <code>a[b]</code><code>a<:b:></code>

|

|

| <br/>

|

|-

| colspan="2" | Conversion

| style="text-align:center;" | <code>R(a)</code><br><code>R{a}</code>

{| class="wikitable" style="width:30%; text-align:center;"

! Keyword || Operator

|-

| || <code>&&</code>

|-

| || <code>&=</code>

|-

| || <code>&</code>

|-

| || <code>&#x7C;</code>

|-

| || <code>~</code>

|-

| || <code>!</code>

|-

| || <code>!=</code>

|-

| || <code>&#x7C;&#x7C;</code>

|-

| || <code>&#x7C;=</code>

|-

| || <code>^</code>

|-

| || <code>^=</code>

|}

Each keyword is a different way to specify an operator and as such can be used instead of the corresponding symbolic variation. For example, and specify the same behavior. As another example, the <code>bitand</code> keyword may be used to replace not only the bitwise-and operator but also the address-of operator, and it can be used to specify reference types (e.g., ).

The ISO C specification makes allowance for these keywords as preprocessor macros in the header file iso646.h|. For compatibility with C, C++ also provides the header , the inclusion of which has no effect. Until C++20, it also provided the corresponding header ciso646| which had no effect as well.

Expression evaluation order

During expression evaluation, the order in which sub-expressions are evaluated is determined by precedence and associativity. An operator with higher precedence is evaluated before a operator of lower precedence and the operands of an operator are evaluated based on associativity. The following table describes the precedence and associativity of the C and C++ operators. Operators are shown in groups of equal precedence with groups ordered in descending precedence from top to bottom (lower order is higher precedence).

Operator precedence is not affected by overloading.

{| class="wikitable"

|-

! style="text-align: left" | Order

! style="text-align: left" | Operator

! style="text-align: left" | Description

! style="text-align: left" | Associativity

|-

! 1

<small>highest</small>

| <code>::</code>

| Scope resolution (C++ only)

| None

|-

! rowspan=11| 2

| style="border-bottom-style: none" | <code>++</code>

| style="border-bottom-style: none" | Postfix increment

| style="vertical-align: top" rowspan="11" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>--</code>

| style="border-bottom-style: none; border-top-style: none" | Postfix decrement

|-

| style="border-bottom-style: none; border-top-style: none" | <code>()</code>

| style="border-bottom-style: none; border-top-style: none" | Function call

|-

| style="border-bottom-style: none; border-top-style: none" | <code>[]</code>

| style="border-bottom-style: none; border-top-style: none" | Array subscripting

|-

| style="border-bottom-style: none; border-top-style: none" | <code>.</code>

| style="border-bottom-style: none; border-top-style: none" | Element selection by reference

|-

| style="border-bottom-style: none; border-top-style: none" | <code>-&gt;</code>

| style="border-bottom-style: none; border-top-style: none" | Element selection through pointer

|-

| style="border-bottom-style: none; border-top-style: none" | <code>typeid()</code>

| style="border-bottom-style: none; border-top-style: none" | Run-time type information (C++ only) (see typeid)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>const_cast</code>

| style="border-bottom-style: none; border-top-style: none" | Type cast (C++ only) (see const_cast)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>dynamic_cast</code>

| style="border-bottom-style: none; border-top-style: none" | Type cast (C++ only) (see dynamic cast)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>reinterpret_cast</code>

| style="border-bottom-style: none; border-top-style: none" | Type cast (C++ only) (see reinterpret_cast)

|-

| style="border-top-style: none" | <code>static_cast</code>

| style="border-top-style: none" | Type cast (C++ only) (see static_cast)

|-

! rowspan="13" | 3

| style="border-bottom-style: none" | <code>++</code>

| style="border-bottom-style: none" | Prefix increment

| rowspan="13" style="vertical-align: top" | Right-to-left

|-

| style="border-bottom-style: none; border-top-style: none" | <code>--</code>

| style="border-bottom-style: none; border-top-style: none" | Prefix decrement

|-

| style="border-bottom-style: none; border-top-style: none" | <code>+</code>

| style="border-bottom-style: none; border-top-style: none" | Unary plus

|-

| style="border-bottom-style: none; border-top-style: none" | <code>-</code>

| style="border-bottom-style: none; border-top-style: none" | Unary minus

|-

| style="border-bottom-style: none; border-top-style: none" | <code>!</code>

| style="border-bottom-style: none; border-top-style: none" | Logical NOT

|-

| style="border-bottom-style: none; border-top-style: none" | <code>~</code>

| style="border-bottom-style: none; border-top-style: none" | Bitwise NOT (ones' complement)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>(type)</code>

| style="border-bottom-style: none; border-top-style: none" | Type cast

|-

| style="border-bottom-style: none; border-top-style: none" | <code>*</code>

| style="border-bottom-style: none; border-top-style: none" | Indirection (dereference)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&</code>

| style="border-bottom-style: none; border-top-style: none" | Address-of

|-

| style="border-bottom-style: none; border-top-style: none" | <code>sizeof</code>

| style="border-bottom-style: none; border-top-style: none" | Sizeof

|-

| style="border-bottom-style: none; border-top-style: none" | <code>_Alignof</code>

| style="border-bottom-style: none; border-top-style: none" | Alignment requirement (since C11)

|-

| style="border-bottom-style: none; border-top-style: none" | <code>new</code>, <code>new[]</code>

| style="border-bottom-style: none; border-top-style: none" | Dynamic memory allocation (C++ only)

|-

| style="border-top-style: none" | <code>delete</code>, <code>delete[]</code>

| style="border-top-style: none" | Dynamic memory deallocation (C++ only)

|-

! rowspan=2| 4

| style="border-bottom-style: none" | <code>.*</code>

| style="border-bottom-style: none" | Pointer to member (C++ only)

| style="vertical-align: top" rowspan="2" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>->*</code>

| style="border-bottom-style: none; border-top-style: none" | Pointer to member (C++ only)

|-

! rowspan=3| 5

| style="border-bottom-style: none" | <code>*</code>

| style="border-bottom-style: none" | Multiplication

| style="vertical-align: top" rowspan="3" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>/</code>

| style="border-bottom-style: none; border-top-style: none" | Division

|-

| style="border-bottom-style: none; border-top-style: none" | <code>%</code>

| style="border-bottom-style: none; border-top-style: none" | Modulo (remainder)

|-

! rowspan=2| 6

| style="border-bottom-style: none" | <code>+</code>

| style="border-bottom-style: none" | Addition

| style="vertical-align: top" rowspan="2" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>-</code>

| style="border-bottom-style: none; border-top-style: none" | Subtraction

|-

! rowspan=2| 7

| style="border-bottom-style: none" | <code>&lt;&lt;</code>

| style="border-bottom-style: none" | Bitwise left shift

| style="vertical-align: top" rowspan="2" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&gt;&gt;</code>

| style="border-bottom-style: none; border-top-style: none" | Bitwise right shift

|-

! rowspan=1| 8

| style="border-bottom-style:none;" | <code>&lt;=&gt;</code>

| style="border-bottom-style:none;" | Three-way comparison (Introduced in C++20 - C++ only)

| style="vertical-align: top" rowspan="1" | Left-to-right

|-

! rowspan=4| 9

| style="border-bottom-style: none" | <code>&lt;</code>

| style="border-bottom-style: none" | Less than

| style="vertical-align: top" rowspan="4" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&lt;=</code>

| style="border-bottom-style: none; border-top-style: none" | Less than or equal to

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&gt;</code>

| style="border-bottom-style: none; border-top-style: none" | Greater than

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&gt;=</code>

| style="border-bottom-style: none; border-top-style: none" | Greater than or equal to

|-

! rowspan=2| 10

| style="border-bottom-style: none" | <code>==</code>

| style="border-bottom-style: none" | Equal to

| style="vertical-align: top" rowspan="2" | Left-to-right

|-

| style="border-bottom-style: none; border-top-style: none" | <code>!=</code>

| style="border-bottom-style: none; border-top-style: none" | Not equal to

|-

! 11

| <code>&</code>

| Bitwise AND

| Left-to-right

|-

! 12

| <code>^</code>

| Bitwise XOR (exclusive or)

| Left-to-right

|-

! 13

| <code><nowiki>|</nowiki></code>

| Bitwise OR (inclusive or)

| Left-to-right

|-

! 14

| <code>&&</code>

| Logical AND

| Left-to-right

|-

! 15

| <code><nowiki>||</nowiki></code>

| Logical OR

| Left-to-right

|-

! rowspan="2" | 16

| style="border-bottom-style: none" | <code>co_await</code>

| rowspan="2" | Coroutine processing (C++ only)

| rowspan="2" | Right-to-left

|-

| style="border-top-style: none" | <code>co_yield</code>

|-

! rowspan="13" | 17

| style="border-bottom-style: none" | <code>?:</code>

| style="border-bottom-style: none" | Ternary conditional operator

| rowspan="13" | Right-to-left

|-

| style="border-bottom-style: none; border-top-style: none" | <code>=</code>

| style="border-bottom-style: none; border-top-style: none" | Direct assignment

|-

| style="border-bottom-style: none; border-top-style: none" | <code>+=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by sum

|-

| style="border-bottom-style: none; border-top-style: none" | <code>-=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by difference

|-

| style="border-bottom-style: none; border-top-style: none" | <code>*=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by product

|-

| style="border-bottom-style: none; border-top-style: none" | <code>/=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by quotient

|-

| style="border-bottom-style: none; border-top-style: none" | <code>%=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by remainder

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&lt;&lt;=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by bitwise left shift

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&gt;&gt;=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by bitwise right shift

|-

| style="border-bottom-style: none; border-top-style: none" | <code>&=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by bitwise AND

|-

| style="border-bottom-style: none; border-top-style: none" | <code>^=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by bitwise XOR

|-

| style="border-bottom-style: none; border-top-style: none" | <code><nowiki>|</nowiki>=</code>

| style="border-bottom-style: none; border-top-style: none" | Assignment by bitwise OR

|-

| style="border-top-style: none" | <code>throw</code>

| style="border-top-style: none" | Throw operator (exceptions throwing, C++ only)

|-

! 18

<small>lowest</small>

| <code>,</code>

| Comma

| Left-to-right

|}

Details

Although this table is adequate for describing most evaluation order, it does not describe a few details. The ternary operator allows any arbitrary expression as its middle operand, despite being listed as having higher precedence than the assignment and comma operators. Thus <code>a ? b, c : d</code> is interpreted as <code>a ? (b, c) : d</code>, and not as the meaningless <code>(a ? b), (c : d)</code>. So, the expression in the middle of the conditional operator (between <code>?</code> and <code>:</code>) is parsed as if parenthesized. Also, the immediate, un-parenthesized result of a C cast expression cannot be the operand of <code>sizeof</code>. Therefore, <code>sizeof (int) * x</code> is interpreted as <code>(sizeof(int)) * x</code> and not <code>sizeof ((int) * x)</code>.

Chained expressions

The precedence table determines the order of binding in chained expressions, when it is not expressly specified by parentheses.

  • For example, <code>++x*3</code> is ambiguous without some precedence rule(s). The precedence table tells us that: is 'bound' more tightly to than to , so that whatever does (now or later—see below), it does it ONLY to (and not to <code>x*3</code>); it is equivalent to (<code>++x</code>, <code>x*3</code>).
  • Similarly, with <code>3*x++</code>, where though the post-fix is designed to act AFTER the entire expression is evaluated, the precedence table makes it clear that ONLY gets incremented (and NOT <code>3*x</code>). In fact, the expression (<code>tmp=x++</code>, <code>3*tmp</code>) is evaluated with being a temporary value. It is functionally equivalent to something like (<code>tmp=3*x</code>, <code>++x</code>, <code>tmp</code>).

center|thumb|Precedence and bindings

  • Abstracting the issue of precedence or binding, consider the diagram above for the expression 3+2*y[i]++. The compiler's job is to resolve the diagram into an expression, one in which several unary operators (call them 3+( . ), 2*( . ), ( . )++ and ( . )[ i ]) are competing to bind to y. The order of precedence table resolves the final sub-expression they each act upon: ( . )[ i ] acts only on y, ( . )++ acts only on y[i], 2*( . ) acts only on y[i]++ and 3+( . ) acts 'only' on 2*((y[i])++). WHAT sub-expression gets acted on by each operator is clear from the precedence table but WHEN each operator acts is not resolved by the precedence table; in this example, the ( . )++ operator acts only on y[i] by the precedence rules but binding levels alone do not indicate the timing of the postfix ++ (the ( . )++ operator acts only after y[i] is evaluated in the expression).

Binding

The binding of operators in C and C++ is specified by a factored language grammar, rather than a precedence table. This creates some subtle conflicts. For example, in C, the syntax for a conditional expression is:

<syntaxhighlight lang="c">logical-OR-expression ? expression : conditional-expression</syntaxhighlight>

while in C++ it is:

<syntaxhighlight lang="cpp">logical-OR-expression ? expression : assignment-expression</syntaxhighlight>

Hence, the expression:

<syntaxhighlight lang="text">e = a < d ? a++ : a = d</syntaxhighlight>

is parsed differently in the two languages. In C, this expression is a syntax error, because the syntax for an assignment expression in C is:

<syntaxhighlight lang="c">unary-expression '=' assignment-expression</syntaxhighlight>

In C++, it is parsed as:

<syntaxhighlight lang="cpp">e = (a < d ? a++ : (a = d))</syntaxhighlight>

which is a valid expression.

To use the comma operator in a function call argument expression, variable assignment, or a comma-separated list, use of parentheses is required. For example,

<syntaxhighlight lang="cpp">

int a = 1, b = 2, weirdVariable = (++a, b), d = 4;

</syntaxhighlight>

Criticism of bitwise and equality operators precedence

The precedence of the bitwise logical operators has been criticized. Conceptually, & and | are arithmetic operators like * and +.

The expression is syntactically parsed as whereas the expression is parsed as . This requires parentheses to be used more often than they otherwise would.

Historically, there was no syntactic distinction between the bitwise and logical operators. In BCPL, B and early C, the operators didn't exist. Instead had different meaning depending on whether they are used in a 'truth-value context' (i.e. when a Boolean value was expected, for example in it behaved as a logical operator, but in it behaved as a bitwise one). It was retained so as to keep backward compatibility with existing installations.

Moreover, in C++ (and later versions of C) equality operations, with the exception of the three-way comparison operator, yield bool type values which are conceptually a single bit (1 or 0) and as such do not properly belong in "bitwise" operations.

Notes

See also

References

  • .
  • C Operator Precedence
  • .