Operators in C and C++
Script error: No such module "Message box". Template:Short description Template:Use American English Script error: No such module "Unsubst". 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 | Syntax | C++ prototype | ||
|---|---|---|---|---|
| in class K | outside class | |||
| Template:Rh colspan="2" | Addition | a + b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Subtraction | a - b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Unary plus; integer promotion | +a
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Unary minus; additive inverse | -a
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Multiplication | a * b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Division | a / b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Modulo[lower-alpha 1] | a % b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Prefix increment | ++a
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Postfix increment | a++
|
Template:CppTemplate:Efn | Template:CppTemplate:Efn | |
| Template:Rh colspan="2" | Prefix decrement | --a
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Postfix decrement | a--
|
Template:CppTemplate:Efn | Template:CppTemplate:Efn | |
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.[1]
| Operation | Syntax | In C | C++ prototype | ||
|---|---|---|---|---|---|
| in class K | outside class | ||||
| Template:Rh colspan="2" | Equal to | a == b
|
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Not equal to | a != b |
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Greater than | a > b |
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Less than | a < b |
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Greater than or equal to | a >= b |
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Less than or equal to | a <= b |
Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Three-way comparison[lower-alpha 2]Template:Efn | a <=> b |
No | Template:Cpp | Template:Cpp | |
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.[2]
| Operation | Syntax | C++ prototype | ||
|---|---|---|---|---|
| in class K | outside class | |||
| Template:Rh colspan="2" | NOT | !a
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | AND | a && b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | 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 | Syntax | C++ prototype | ||
|---|---|---|---|---|
| in class K | outside class | |||
| Template:Rh colspan="2" | NOT | ~a |
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | AND | a & b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | OR | a | b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | XOR | a ^ b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Shift left[lower-alpha 3] | a << b
|
Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Shift right[lower-alpha 3]Template:Refn | a >> b
|
Template:Cpp | Template:Cpp | |
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 | |
|---|---|---|---|
| in class K | outside class | ||
| Template:Rh | Assignment | a = b
|
Template:Cpp | — |
| Template:Rh | Addition combination | a += b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Subtraction combination | a -= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Multiplication combination | a *= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Division combination | a /= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Modulo combination | a %= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Bitwise AND combination | a &= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Bitwise OR combination | a |= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Bitwise XOR combination | a ^= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Bitwise left shift combination | a <<= b
|
Template:Cpp | Template:Cpp |
| Template:Rh | Bitwise right shift combinationTemplate:Refn | a >>= b
|
Template:Cpp | Template:Cpp |
Member and pointer
| Operation | Syntax | Can overload | In C | C++ prototype | ||
|---|---|---|---|---|---|---|
| in class K | outside class | |||||
| Template:Rh colspan="2" | Subscript | a[b]a<:b:>[3]
|
Yes | Yes | Template:Cpp Template:Cpp[lower-alpha 4] |
— | |
| Template:Rh colspan="2" | Indirection (object pointed to by a)Script error: No such module "Check for unknown parameters". |
*a |
Yes | Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Address-of (address of a)Script error: No such module "Check for unknown parameters". |
&a |
Yes[lower-alpha 5] | Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Structure dereference (member b of object pointed to by a)Script error: No such module "Check for unknown parameters". |
a->b |
Yes | Yes | Template:Cpp[lower-alpha 6] |
— | |
| Template:Rh colspan="2" | Structure reference (member b of object a)Script error: No such module "Check for unknown parameters". |
a.b |
No | Yes | Template:Rh colspan="2" data-sort-value="" style="background: var(--background-color-interactive, #ececec); color: var(--color-base, inherit); vertical-align: middle; text-align: center; " class="table-na" | — | ||
| Template:Rh colspan="2" | Member selected by pointer-to-member b of object pointed to by a[lower-alpha 7] | a->*b |
Yes | No | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Member of object a selected by pointer-to-member b | a.*b |
No | No | Template:Rh colspan="2" data-sort-value="" style="background: var(--background-color-interactive, #ececec); color: var(--color-base, inherit); vertical-align: middle; text-align: center; " class="table-na" | — | ||
Other
| Operation | Syntax | Can overload | In C | C++ prototype | ||
|---|---|---|---|---|---|---|
| in class K | outside class | |||||
| Template:Rh colspan="2" | Function call | a(a1, a2)
|
Yes | Yes | Template:Cpp | — | |
| Template:Rh colspan="2" | Comma | a, b |
Yes | Yes | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Ternary conditional | a ? b : c |
No | Yes | — | ||
| Template:Rh colspan="2" | Scope resolution | a::b[lower-alpha 8] |
No | No | — | ||
| Template:Rh colspan="2" | User-defined literals[lower-alpha 9][lower-alpha 10] | "a"_b |
Yes | No | — | Template:Cpp | |
| Template:Rh colspan="2" | Sizeof | sizeof a[lower-alpha 11]sizeof (R) |
No | Yes | — | ||
| Template:Rh colspan="2" | Size of parameter pack[lower-alpha 10] | sizeof...(Args) |
No | No | — | ||
| Template:Rh colspan="2" | Alignof[lower-alpha 10] | alignof(R) or _Alignof(R)[lower-alpha 12] |
No | Yes | — | ||
| Template:Rh colspan="2" | Typeof[lower-alpha 13] | typeof(a)typeof(R)typeof_unqual(a)typeof_unqual(R) |
— | Yes | — | ||
| Template:Rh colspan="2" | Decltype[lower-alpha 10] | decltype (a)decltype (R) |
No | No | — | ||
| Template:Rh colspan="2" | Type identification | typeid(a)typeid(R) |
No | No | — | ||
| Template:Rh colspan="2" | Conversion (C-style cast)Script error: No such module "Check for unknown parameters". |
(R)a |
Yes | Yes | Template:Cpp[4] | — | |
| Template:Rh colspan="2" | ConversionTemplate:Efn[5] | R(a)R{a}[lower-alpha 10]auto(a)[lower-alpha 4]auto{a}[lower-alpha 4] |
No | No | Template:Rh colspan="2" data-sort-value="" style="background: var(--background-color-interactive, #ececec); color: var(--color-base, inherit); vertical-align: middle; text-align: center; " class="table-na" | — | ||
| Template:Rh colspan="2" | static_cast conversionTemplate:Efn | static_cast<R>(a) |
Yes | No | Template:Cpp Template:Cpp[lower-alpha 10] |
— | |
| Template:Rh colspan="2" | dynamic cast conversion | dynamic_cast<R>(a) |
No | No | — | ||
| Template:Rh colspan="2" | const_cast conversion | const_cast<R>(a) |
No | No | — | ||
| Template:Rh colspan="2" | reinterpret_cast conversion | reinterpret_cast<R>(a) |
No | No | — | ||
| Template:Rh colspan="2" | Allocate memory | new R[lower-alpha 14] |
Yes | No | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Allocate array | new R[n][lower-alpha 15] |
Yes | No | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Deallocate memory | delete a |
Yes | No | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Deallocate array | delete[] a |
Yes | No | Template:Cpp | Template:Cpp | |
| Template:Rh colspan="2" | Exception check[lower-alpha 10] | noexcept(a) |
No | No | — | ||
Synonyms
C++ defines keywords to act as aliases for a number of operators:[6]
| 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).[7][8][9]
Operator precedence is not affected by overloading.
| Order | Operator | Description | Associativity |
|---|---|---|---|
| 1
highest |
::
|
Scope resolution (C++ only) | None |
| 2 | ++
|
Postfix increment | Left-to-right |
--
|
Postfix decrement | ||
()
|
Function call | ||
[]
|
Array subscripting | ||
.
|
Element selection by reference | ||
->
|
Element selection through pointer | ||
typeid()
|
Run-time type information (C++ only) (see typeid) | ||
const_cast
|
Type cast (C++ only) (see const_cast) | ||
dynamic_cast
|
Type cast (C++ only) (see dynamic cast) | ||
reinterpret_cast
|
Type cast (C++ only) (see reinterpret_cast) | ||
static_cast
|
Type cast (C++ only) (see static_cast) | ||
| 3 | ++
|
Prefix increment | Right-to-left |
--
|
Prefix decrement | ||
+
|
Unary plus | ||
-
|
Unary minus | ||
!
|
Logical NOT | ||
~
|
Bitwise NOT (ones' complement) | ||
(type)
|
Type cast | ||
*
|
Indirection (dereference) | ||
&
|
Address-of | ||
sizeof
|
Sizeof | ||
_Alignof
|
Alignment requirement (since C11) | ||
new, new[]
|
Dynamic memory allocation (C++ only) | ||
delete, delete[]
|
Dynamic memory deallocation (C++ only) | ||
| 4 | .*
|
Pointer to member (C++ only) | Left-to-right |
->*
|
Pointer to member (C++ only) | ||
| 5 | *
|
Multiplication | Left-to-right |
/
|
Division | ||
%
|
Modulo (remainder) | ||
| 6 | +
|
Addition | Left-to-right |
-
|
Subtraction | ||
| 7 | <<
|
Bitwise left shift | Left-to-right |
>>
|
Bitwise right shift | ||
| 8 | <=>
|
Three-way comparison (Introduced in C++20 - C++ only) | Left-to-right |
| 9 | <
|
Less than | Left-to-right |
<=
|
Less than or equal to | ||
>
|
Greater than | ||
>=
|
Greater than or equal to | ||
| 10 | ==
|
Equal to | Left-to-right |
!=
|
Not equal to | ||
| 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 |
co_yield
| |||
| 17 | ?:
|
Ternary conditional operator | Right-to-left |
=
|
Direct assignment | ||
+=
|
Assignment by sum | ||
-=
|
Assignment by difference | ||
*=
|
Assignment by product | ||
/=
|
Assignment by quotient | ||
%=
|
Assignment by remainder | ||
<<=
|
Assignment by bitwise left shift | ||
>>=
|
Assignment by bitwise right shift | ||
&=
|
Assignment by bitwise AND | ||
^=
|
Assignment by bitwise XOR | ||
|=
|
Assignment by bitwise OR | ||
throw
|
Throw operator (exceptions throwing, C++ only) | ||
| 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*3is ambiguous without some precedence rule(s). The precedence table tells us that: <templatestyles src="Mono/styles.css" />x is 'bound' more tightly to <templatestyles src="Mono/styles.css" />++ than to <templatestyles src="Mono/styles.css" />*, so that whatever <templatestyles src="Mono/styles.css" />++ does (now or later—see below), it does it ONLY to <templatestyles src="Mono/styles.css" />x (and not tox*3); it is equivalent to (++x,x*3). - Similarly, with
3*x++, where though the post-fix <templatestyles src="Mono/styles.css" />++ is designed to act AFTER the entire expression is evaluated, the precedence table makes it clear that ONLY <templatestyles src="Mono/styles.css" />x gets incremented (and NOT3*x). In fact, the expression (tmp=x++,3*tmp) is evaluated with <templatestyles src="Mono/styles.css" />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:
logical-OR-expression ? expression : conditional-expression
while in C++ it is:
logical-OR-expression ? expression : assignment-expression
Hence, the expression:
e = a < d ? a++ : a = d
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:
unary-expression '=' assignment-expression
In C++, it is parsed as:
e = (a < d ? a++ : (a = d))
which is a valid expression.[10][11]
To use the comma operator in a function call argument expression, variable assignment, or a comma-separated list, use of parentheses is required.[12][13] For example,
int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
Criticism of bitwise and equality operators precedence
The precedence of the bitwise logical operators has been criticized.[14] Conceptually, & and | are arithmetic operators like * and +.
The expression Template:Cpp is syntactically parsed as Template:Cpp whereas the expression Template:Cpp is parsed as Template:Cpp. 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 Template:Cpp didn't exist. Instead Template:Cpp 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 Template:Cpp it behaved as a logical operator, but in Template:Cpp it behaved as a bitwise one). It was retained so as to keep backward compatibility with existing installations.[15]
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
<templatestyles src="Reflist/styles.css" />
- ↑ The modulus operator only supports integer operands; for floating point, a function such as
fmodcan be used. - ↑ About C++20 three-way comparison
- ↑ a b In the context of iostreams in C++, writers often will refer to Template:Cpp and Template:Cpp as the "put-to" or "stream insertion" and "get-from" or "stream extraction" operators, respectively.
- ↑ a b c since C++23
- ↑ The actual address of an object with an overloaded
operator &can be obtained withstd::addressof - ↑ The return type of Template:Cpp must be a type for which the Template:Cpp operation can be applied, such as a pointer type. If Template:Cpp is of type Template:Cpp where Template:Cpp overloads Template:Cpp, Template:Cpp gets expanded to Template:Cpp.
- ↑ Script error: No such module "citation/CS1"..
- ↑ Although a
::punctuator exists in C as of C23, it is not used as a scope resolution operator. - ↑ About C++11 User-defined literals
- ↑ a b c d e f g since C++11
- ↑ The parentheses are not necessary when taking the size of a value, only when taking the size of a type. However, they are usually used regardless.Script error: No such module "Unsubst".
- ↑ C++ defines
alignofoperator, whereas C defines_Alignof(C23 defines both). Both operators have the same semantics. - ↑ since C23; not in standard C++
- ↑ The type name can also be inferred (e.g
new auto) if an initializer is provided. - ↑ The array size can also be inferred if an initializer is provided.
Script error: No such module "Check for unknown parameters".
See also
- Template:Annotated link
- Template:Annotated link
- Template:Annotated link
- Template:Annotated link
- Template:Annotated link
References
<templatestyles src="Reflist/styles.css" />
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Explicit type conversion in C++
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1"..
- ↑ Script error: No such module "citation/CS1".
Script error: No such module "Check for unknown parameters".
External links
- Script error: No such module "citation/CS1"..
- C Operator Precedence
- Script error: No such module "citation/CS1"..