# Operators in C and C++

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 &&, ||, and , (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, += and -= 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 a and b represent literal values, object/variable names, or l-values, as appropriate. R, S and T stand for a data type, and K 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++.
| Operation | Operation | Syntax | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | in class K | outside class |
| Addition | Addition | a + b | R K::operator +(S b); | R operator +(K a, S b); |
| Subtraction | Subtraction | a - b | R K::operator -(S b); | R operator -(K a, S b); |
| Unary plus; integer promotion | Unary plus; integer promotion | +a | R K::operator +; | R operator +(K a); |
| Unary minus; additive inverse | Unary minus; additive inverse | -a | R K::operator -; | R operator -(K a); |
| Multiplication | Multiplication | a * b | R K::operator *(S b); | R operator *(K a, S b); |
| Division | Division | a / b | R K::operator /(S b); | R operator /(K a, S b); |
| Modulo | Modulo | a % b | R K::operator %(S b); | R operator %(K a, S b); |
| Prefix increment | Prefix increment | ++a | R& K::operator ++; | R& operator ++(K& a); |
| Postfix increment | Postfix increment | a++ | R K::operator ++(int); | R operator ++(K& a, int); |
| Prefix decrement | Prefix decrement | --a | R& K::operator --; | R& operator --(K& a); |
| Postfix decrement | Postfix decrement | a-- | R K::operator --(int); | R operator --(K& a, int); |

### Relational

All relational (comparison) operators can be overloaded in C++. Since C++20, the inequality operator is automatically generated if operator== is defined and all four relational operators are automatically generated if operator<=> is defined.
| Operation | Operation | Syntax | In C | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | In C | in class K | outside class |
| Equal to | Equal to | a == b | Yes | bool K::operator ==(S const& b) const; | bool operator ==(K const& a, S const& b); |
| Not equal to | Not equal to | a != b | Yes | bool K::operator !=(S const& b) const; | bool operator !=(K const& a, S const& b); |
| Greater than | Greater than | a > b | Yes | bool K::operator >(S const& b) const; | bool operator >(K const& a, S const& b); |
| Less than | Less than | a < b | Yes | bool K::operator <(S const& b) const; | bool operator <(K const& a, S const& b); |
| Greater than or equal to | Greater than or equal to | a >= b | Yes | bool K::operator >=(S const& b) const; | bool operator >=(K const& a, S const& b); |
| Less than or equal to | Less than or equal to | a <= b | Yes | bool K::operator <=(S const& b) const; | bool operator <=(K const& a, S const& b); |
| Three-way comparison | Three-way comparison | a <=> b | No | auto K::operator <=>(const S &b); | auto operator <=>(const K &a, const S &b); |

### Logical

C and C++ have the same logical operators and all can be overloaded in C++.
Note that overloading logical AND and OR is discouraged, because as overloaded operators they always evaluate both operands instead of providing the normal semantics of short-circuit evaluation.
| Operation | Operation | Syntax | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | in class K | outside class |
| NOT | NOT | !a | bool K::operator !; | bool operator !(K a); |
| AND | AND | a && b | bool K::operator &&(S b); | bool operator &&(K a, S b); |
| OR | OR | a || b | bool K::operator ||(S b); | bool operator ||(K a, S b); |

### Bitwise

C and C++ have the same bitwise operators and all can be overloaded in C++.
| Operation | Operation | Syntax | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | in class K | outside class |
| NOT | NOT | ~a | R K::operator ~; | R operator ~(K a); |
| AND | AND | a & b | R K::operator &(S b); | R operator &(K a, S b); |
| OR | OR | a | b | R K::operator |(S b); | R operator |(K a, S b); |
| XOR | XOR | a ^ b | R K::operator ^(S b); | R operator ^(K a, S b); |
| Shift left | Shift left | a << b | R K::operator <<(S b); | R operator <<(K a, S b); |
| Shift right | Shift right | a >> b | R K::operator >>(S b); | R operator >>(K a, S b); |

### Assignment

C and C++ have the same assignment operators and all can be overloaded in C++.
For the combination operators, a ⊚= b (where ⊚ represents an operation) is equivalent to a = a ⊚ b, except that a is evaluated only once.
| Operation | Syntax | C++ prototype | C++ prototype |
| Operation | Syntax | in class K | outside class |
| Assignment | a = b | R& K::operator =(S b); | — |
| Addition combination | a += b | R& K::operator +=(S b); | R& operator +=(K& a, S b); |
| Subtraction combination | a -= b | R& K::operator -=(S b); | R& operator -=(K& a, S b); |
| Multiplication combination | a *= b | R& K::operator *=(S b); | R& operator *=(K& a, S b); |
| Division combination | a /= b | R& K::operator /=(S b); | R& operator /=(K& a, S b); |
| Modulo combination | a %= b | R& K::operator %=(S b); | R& operator %=(K& a, S b); |
| Bitwise AND combination | a &= b | R& K::operator &=(S b); | R& operator &=(K& a, S b); |
| Bitwise OR combination | a |= b | R& K::operator |=(S b); | R& operator |=(K& a, S b); |
| Bitwise XOR combination | a ^= b | R& K::operator ^=(S b); | R& operator ^=(K& a, S b); |
| Bitwise left shift combination | a <<= b | R& K::operator <<=(S b); | R& operator <<=(K& a, S b); |
| Bitwise right shift combination | a >>= b | R& K::operator >>=(S b); | R& operator >>=(K& a, S b); |

### Member and pointer

| Operation | Operation | Syntax | Can overload | In C | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | Can overload | In C | in class K | outside class |
| Subscript | Subscript | a[b]a<:b:> | Yes | Yes | R& K::operator(S b); R& K::operator(S b, ...); | — |
| Indirection (object pointed to by a) | Indirection (object pointed to by a) | *a | Yes | Yes | R& K::operator *; | R& operator *(K a); |
| Address-of (address of a) | Address-of (address of a) | &a | Yes | Yes | R* K::operator &; | R* operator &(K a); |
| Structure dereference (member b of object pointed to by a) | Structure dereference (member b of object pointed to by a) | a->b | Yes | Yes | R* K::operator ->; | — |
| Structure reference (member b of object a) | Structure reference (member b of object a) | a.b | No | Yes | — | — |
| Member selected by pointer-to-member b of object pointed to by a | Member selected by pointer-to-member b of object pointed to by a | a->*b | Yes | No | R& K::operator ->*(S b); | R& operator ->*(K a, S b); |
| Member of object a selected by pointer-to-member b | Member of object a selected by pointer-to-member b | a.*b | No | No | — | — |

### Other

| Operation | Operation | Syntax | Can overload | In C | C++ prototype | C++ prototype |
| Operation | Operation | Syntax | Can overload | In C | in class K | outside class |
| Function call | Function call | a(a1, a2) | Yes | Yes | R K::operator(S a, T b, ...); | — |
| Comma | Comma | a, b | Yes | Yes | R K::operator ,(S b); | R operator ,(K a, S b); |
| Ternary conditional | Ternary conditional | a ? b : c | No | Yes | — | — |
| Scope resolution | Scope resolution | a::b | No | No | — | — |
| User-defined literals | User-defined literals | "a"_b | Yes | No | — | R operator "" _b(T a) |
| Sizeof | Sizeof | sizeof a sizeof (R) | No | Yes | — | — |
| Size of parameter pack | Size of parameter pack | sizeof...(Args) | No | No | — | — |
| Alignof | Alignof | alignof(R) or _Alignof(R) | No | Yes | — | — |
| Decltype | Decltype | decltype (a) decltype (R) | No | No | — | — |
| Type identification | Type identification | typeid(a) typeid(R) | No | No | — | — |
| Conversion (C-style cast) | Conversion (C-style cast) | (R)a | Yes | Yes | K::operator R; | — |
| Conversion | Conversion | R(a) R{a} auto(a) auto{a} | No | No | — | — |
| static_cast conversion | static_cast conversion | static_cast<R>(a) | Yes | No | K::operator R; explicit K::operator R; | — |
| dynamic cast conversion | dynamic cast conversion | dynamic_cast<R>(a) | No | No | — | — |
| const_cast conversion | const_cast conversion | const_cast<R>(a) | No | No | — | — |
| reinterpret_cast conversion | reinterpret_cast conversion | reinterpret_cast<R>(a) | No | No | — | — |
| Allocate storage | Allocate storage | new R | Yes | No | void* K::operator new(size_t x); | void* operator new(size_t x); |
| Allocate array | Allocate array | new R[n] | Yes | No | void* K::operator new(size_t a); | void* operator new(size_t a); |
| Deallocate storage | Deallocate storage | delete a | Yes | No | void K::operator delete(void* a); | void operator delete(void* a); |
| Deallocate array | Deallocate array | delete a | Yes | No | void K::operator delete(void* a); | void operator delete(void* a); |
| Exception check | Exception check | noexcept(a) | No | No | — | — |

### Synonyms

C++ defines keywords to act as aliases for a number of operators:
| Keyword | Operator |
| and | && |
| and_eq | &= |
| bitand | & |
| bitor | | |
| compl | ~ |
| not | ! |
| not_eq | != |
| or | || |
| or_eq | |= |
| xor | ^ |
| xor_eq | ^= |
Each keyword is a different way to specify an operator and as such can be used instead of the corresponding symbolic variation. For example, (a > 0 and not flag) and (a > 0 && !flag) specify the same behavior. As another example, the bitand 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., int bitand ref = n).
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 iso646.h, 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.
| Order | Operator | Description | Associativity |
| 1 highest | :: | Scope resolution (C++ only) | None |
| 2 | ++ | Postfix increment | Left-to-right |
| 2 | -- | Postfix decrement | Left-to-right |
| 2 | | Function call | Left-to-right |
| 2 | | Array subscripting | Left-to-right |
| 2 | . | Element selection by reference | Left-to-right |
| 2 | -> | Element selection through pointer | Left-to-right |
| 2 | typeid | Run-time type information (C++ only) (see typeid) | Left-to-right |
| 2 | const_cast | Type cast (C++ only) (see const_cast) | Left-to-right |
| 2 | dynamic_cast | Type cast (C++ only) (see dynamic cast) | Left-to-right |
| 2 | reinterpret_cast | Type cast (C++ only) (see reinterpret_cast) | Left-to-right |
| 2 | static_cast | Type cast (C++ only) (see static_cast) | Left-to-right |
| 3 | ++ | Prefix increment | Right-to-left |
| 3 | -- | Prefix decrement | Right-to-left |
| 3 | + | Unary plus | Right-to-left |
| 3 | - | Unary minus | Right-to-left |
| 3 | ! | Logical NOT | Right-to-left |
| 3 | ~ | Bitwise NOT (ones' complement) | Right-to-left |
| 3 | (type) | Type cast | Right-to-left |
| 3 | * | Indirection (dereference) | Right-to-left |
| 3 | & | Address-of | Right-to-left |
| 3 | sizeof | Sizeof | Right-to-left |
| 3 | _Alignof | Alignment requirement (since C11) | Right-to-left |
| 3 | new, new | Dynamic memory allocation (C++ only) | Right-to-left |
| 3 | delete, delete | Dynamic memory deallocation (C++ only) | Right-to-left |
| 4 | .* | Pointer to member (C++ only) | Left-to-right |
| 4 | ->* | Pointer to member (C++ only) | Left-to-right |
| 5 | * | Multiplication | Left-to-right |
| 5 | / | Division | Left-to-right |
| 5 | % | Modulo (remainder) | Left-to-right |
| 6 | + | Addition | Left-to-right |
| 6 | - | Subtraction | Left-to-right |
| 7 | << | Bitwise left shift | Left-to-right |
| 7 | >> | Bitwise right shift | Left-to-right |
| 8 | <=> | Three-way comparison (Introduced in C++20 - C++ only) | Left-to-right |
| 9 | < | Less than | Left-to-right |
| 9 | <= | Less than or equal to | Left-to-right |
| 9 | > | Greater than | Left-to-right |
| 9 | >= | Greater than or equal to | Left-to-right |
| 10 | == | Equal to | Left-to-right |
| 10 | != | Not equal to | Left-to-right |
| 11 | & | Bitwise AND | Left-to-right |
| 12 | ^ | Bitwise XOR (exclusive or) | Left-to-right |
| 13 | | | Bitwise OR (inclusive or) | Left-to-right |
| 14 | && | Logical AND | Left-to-right |
| 15 | || | Logical OR | Left-to-right |
| 16 | co_await | Coroutine processing (C++ only) | Right-to-left |
| 16 | co_yield | Coroutine processing (C++ only) | Right-to-left |
| 17 | ?: | Ternary conditional operator | Right-to-left |
| 17 | = | Direct assignment | Right-to-left |
| 17 | += | Assignment by sum | Right-to-left |
| 17 | -= | Assignment by difference | Right-to-left |
| 17 | *= | Assignment by product | Right-to-left |
| 17 | /= | Assignment by quotient | Right-to-left |
| 17 | %= | Assignment by remainder | Right-to-left |
| 17 | <<= | Assignment by bitwise left shift | Right-to-left |
| 17 | >>= | Assignment by bitwise right shift | Right-to-left |
| 17 | &= | Assignment by bitwise AND | Right-to-left |
| 17 | ^= | Assignment by bitwise XOR | Right-to-left |
| 17 | |= | Assignment by bitwise OR | Right-to-left |
| 17 | throw | Throw operator (exceptions throwing, C++ only) | Right-to-left |
| 18 lowest | , | 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 a ? b, c : d is interpreted as a ? (b, c) : d, and not as the meaningless (a ? b), (c : d). So, the expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized. Also, the immediate, un-parenthesized result of a C cast expression cannot be the operand of sizeof. Therefore, sizeof (int) * x is interpreted as (sizeof(int)) * x and not sizeof ((int) * x).

### Chained expressions

The precedence table determines the order of binding in chained expressions, when it is not expressly specified by parentheses.
* For example, ++x*3 is ambiguous without some precedence rule(s). The precedence table tells us that: x is 'bound' more tightly to ++ than to *, so that whatever ++ does (now or later—see below), it does it ONLY to x (and not to x*3); it is equivalent to (++x, x*3).
* Similarly, with 3*x++, where though the post-fix ++ is designed to act AFTER the entire expression is evaluated, the precedence table makes it clear that ONLY x gets incremented (and NOT 3*x). In fact, the expression (tmp=x++, 3*tmp) is evaluated with tmp being a temporary value. It is functionally equivalent to something like (tmp=3*x, ++x, tmp).
* 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])++). It is important to note that 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:
while in C++ it is:
Hence, the expression:
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:
In C++, it is parsed as:
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,

### 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 a & b == 7 is syntactically parsed as a & (b == 7) whereas the expression a + b == 7 is parsed as (a + b) == 7. 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 if (a==b & c) {...} it behaved as a logical operator, but in c = a & b 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.