Operators in C and C++

Revision as of 02:44, 23 April 2025 by imported>Voltaic181 (→‎Relational: Fixed table spanning incorrectly.)
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

Template:Short description Template:Use American English Template:Use dmy dates 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".

OperatorsEdit

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.

ArithmeticEdit

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 Template:Nowrap 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<ref name="modulo" group="lower-alpha" /> 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

RelationalEdit

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.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

Operation Syntax In C C++ prototype
in class K outside class
Template:Rh colspan="2" | Equal to a == b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Not equal to a != b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Greater than a > b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Less than a < b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Greater than or equal to a >= b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Less than or equal to a <= b Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Three-way comparison<ref name="threewaycomparison" group="lower-alpha"/>Template:Efn a <=> b Template:No Template:Cpp Template:Cpp

LogicalEdit

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.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

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 <syntaxhighlight lang="cpp" class="" style="" inline="1">bool K::operator Template:!!(S b);</syntaxhighlight> <syntaxhighlight lang="cpp" class="" style="" inline="1">bool operator Template:!!(K a, S b);</syntaxhighlight>

BitwiseEdit

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<ref name="bitshift" group="lower-alpha" /> a << b Template:Cpp Template:Cpp
Template:Rh colspan="2" | Shift right<ref name="bitshift" group="lower-alpha" />Template:Refn a >> b Template:Cpp Template:Cpp

AssignmentEdit

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 Template:Nowrap Template:Cpp Template:N/a
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 pointerEdit

Operation Syntax Can overload In C C++ prototype
in class K outside class
Template:Rh colspan="2" | Subscript a[b]a<:b:><ref>{{#invoke:citation/CS1|citation CitationClass=web

}}</ref>

Template:Yes Template:Yes Template:Cpp
Template:Cpp<ref name="sinceCXX23" group="lower-alpha" />
Template:N/a
Template:Rh colspan="2" | Indirection
Template:Small
*a Template:Yes Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Address-of
Template:Small
&a Template:Yes<ref name="addressof2" group="lower-alpha"/> Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Structure dereference
Template:Small
a->b Template:Yes Template:Yes Template:Cpp<ref name="arrowptr" group="lower-alpha" />
Template:N/a
Template:Rh colspan="2" | Structure reference
Template:Small
a.b Template:No Template:Yes Template:Rh colspan="2" Template:N/a
Template:Rh colspan="2" | Member selected by pointer-to-member b of object pointed to by a<ref name="arrowstar" group="lower-alpha" /> a->*b Template:Yes Template:No Template:Cpp Template:Cpp
Template:Rh colspan="2" | Member of object a selected by pointer-to-member b a.*b Template:No Template:No Template:Rh colspan="2" Template:N/a

OtherEdit

Operation Syntax Can overload In C C++ prototype
in class K outside class
Template:Rh colspan="2" | Function call a(a1, a2) Template:Yes Template:Yes Template:Cpp Template:N/a
Template:Rh colspan="2" | Comma a, b Template:Yes Template:Yes Template:Cpp Template:Cpp
Template:Rh colspan="2" | Ternary conditional a ? b : c Template:No Template:Yes colspan="2" Template:N/a
Template:Rh colspan="2" | Scope resolution a::b<ref name="scopal" group="lower-alpha" /> Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | User-defined literals<ref name="ud-literal" group="lower-alpha" /><ref name="sinceCXX11" group="lower-alpha" /> "a"_b Template:Yes Template:No Template:N/a Template:Cpp
Template:Rh colspan="2" | Sizeof sizeof a<ref name="sizeof" group="lower-alpha" />
sizeof (R)
Template:No Template:Yes colspan="2" Template:N/a
Template:Rh colspan="2" | Size of parameter pack<ref name="sinceCXX11" group="lower-alpha" /> sizeof...(Args) Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | Alignof<ref name="sinceCXX11" group="lower-alpha" /> alignof(R)
or _Alignof(R)<ref name="alignof" group="lower-alpha"/>
Template:No Template:Yes colspan="2" Template:N/a
Template:Rh colspan="2" | Decltype<ref name="sinceCXX11" group="lower-alpha" /> decltype (a)
decltype (R)
Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | Type identification typeid(a)
typeid(R)
Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | Conversion
Template:Small
(R)a Template:Yes Template:Yes Template:Cpp<ref>{{#invoke:citation/CS1|citation CitationClass=web

}}</ref>

Template:N/a
Template:Rh colspan="2" | ConversionTemplate:Efn<ref>Explicit type conversion in C++</ref> R(a)
R{a}<ref name="sinceCXX11" group="lower-alpha" />
auto(a)<ref name="sinceCXX23" group="lower-alpha" />
auto{a}<ref name="sinceCXX23" group="lower-alpha" />
Template:No Template:No Template:Rh colspan="2" Template:N/a
Template:Rh colspan="2" | static_cast conversionTemplate:Efn static_cast<R>(a) Template:Yes Template:No Template:Cpp
Template:Cpp<ref name="sinceCXX11" group="lower-alpha" />
Template:N/a
Template:Rh colspan="2" | dynamic cast conversion dynamic_cast<R>(a) Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | const_cast conversion const_cast<R>(a) Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | reinterpret_cast conversion reinterpret_cast<R>(a) Template:No Template:No colspan="2" Template:N/a
Template:Rh colspan="2" | Allocate storage new R<ref name="infer" group="lower-alpha"/> Template:Yes Template:No Template:Cpp Template:Cpp
Template:Rh colspan="2" | Allocate array new R[n]<ref name="infer2" group="lower-alpha"/> Template:Yes Template:No Template:Cpp Template:Cpp
Template:Rh colspan="2" | Deallocate storage delete a Template:Yes Template:No Template:Cpp Template:Cpp
Template:Rh colspan="2" | Deallocate array delete[] a Template:Yes Template:No Template:Cpp Template:Cpp
Template:Rh colspan="2" | Exception check<ref name="sinceCXX11" group="lower-alpha" /> noexcept(a) Template:No Template:No colspan="2" Template:N/a

SynonymsEdit

C++ defines keywords to act as aliases for a number of operators:<ref name="Committee">Template:Cite book</ref>

Keyword Operator
<syntaxhighlight lang="text" class="" style="" inline="1">and</syntaxhighlight> &&
<syntaxhighlight lang="text" class="" style="" inline="1">and_eq</syntaxhighlight> &=
<syntaxhighlight lang="text" class="" style="" inline="1">bitand</syntaxhighlight> &
<syntaxhighlight lang="text" class="" style="" inline="1">bitor</syntaxhighlight> |
<syntaxhighlight lang="text" class="" style="" inline="1">compl</syntaxhighlight> ~
<syntaxhighlight lang="text" class="" style="" inline="1">not</syntaxhighlight> !
<syntaxhighlight lang="text" class="" style="" inline="1">not_eq</syntaxhighlight> !=
<syntaxhighlight lang="text" class="" style="" inline="1">or</syntaxhighlight> ||
<syntaxhighlight lang="text" class="" style="" inline="1">or_eq</syntaxhighlight> |=
<syntaxhighlight lang="text" class="" style="" inline="1">xor</syntaxhighlight> ^
<syntaxhighlight lang="text" class="" style="" inline="1">xor_eq</syntaxhighlight> ^=

Each keyword is a different way to specify an operator and as such can be used instead of the corresponding symbolic variation. For example, <syntaxhighlight lang="text" class="" style="" inline="1">(a > 0 and not flag)</syntaxhighlight> and <syntaxhighlight lang="text" class="" style="" inline="1">(a > 0 && !flag)</syntaxhighlight> 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., <syntaxhighlight lang="text" class="" style="" inline="1">int bitand ref = n</syntaxhighlight>).

The ISO C specification makes allowance for these keywords as preprocessor macros in the header file <syntaxhighlight lang="text" class="" style="" inline="1">iso646.h</syntaxhighlight>. For compatibility with C, C++ also provides the header <syntaxhighlight lang="text" class="" style="" inline="1">iso646.h</syntaxhighlight>, the inclusion of which has no effect. Until C++20, it also provided the corresponding header <syntaxhighlight lang="text" class="" style="" inline="1">ciso646</syntaxhighlight> which had no effect as well.

Expression evaluation orderEdit

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).<ref>Template:Cite book</ref><ref>Template:Cite tech report</ref><ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

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

DetailsEdit

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 expressionsEdit

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: Template:Mono is 'bound' more tightly to Template:Mono than to Template:Mono, so that whatever Template:Mono does (now or later—see below), it does it ONLY to Template:Mono (and not to x*3); it is equivalent to (++x, x*3).
  • Similarly, with 3*x++, where though the post-fix Template:Mono is designed to act AFTER the entire expression is evaluated, the precedence table makes it clear that ONLY Template:Mono gets incremented (and NOT 3*x). In fact, the expression (tmp=x++, 3*tmp) is evaluated with Template:Mono being a temporary value. It is functionally equivalent to something like (tmp=3*x, ++x, tmp).
File:Precedence 2.png
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])++). 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).

BindingEdit

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.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref><ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

To use the comma operator in a function call argument expression, variable assignment, or a comma-separated list, use of parentheses is required.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref><ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> For example,

<syntaxhighlight lang="cpp"> int a = 1, b = 2, weirdVariable = (++a, b), d = 4; </syntaxhighlight>

Criticism of bitwise and equality operators precedenceEdit

The precedence of the bitwise logical operators has been criticized.<ref name="Bell">Template:Citation.</ref> 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.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

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.

NotesEdit

Template:Reflist

See alsoEdit

ReferencesEdit

Template:Reflist

External linksEdit

Template:CProLang Template:C++ programming language