Operators in C and C++

{{short description|List of operators in C and C++}}

{{Use American English|date = March 2019}}

{{Use dmy dates|date=December 2019}}

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++.

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

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

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

in class K

! outside class

{{rh}} colspan="2" | Addition

| align="center" | {{nowrap| 1=a + b}}

| {{cpp|1=R K::operator +(S b);}}

| {{cpp|1=R operator +(K a, S b);}}

{{rh}} colspan="2" | Subtraction

| align="center" | a - b

| {{cpp|1=R K::operator -(S b);}}

| {{cpp|1=R operator -(K a, S b);}}

{{rh}} colspan="2" | Unary plus; integer promotion

|align="center" | +a

| {{cpp|1=R K::operator +();}}

| {{cpp|1=R operator +(K a);}}

{{rh}} colspan="2" | Unary minus; additive inverse

| align="center" | -a

| {{cpp|1=R K::operator -();}}

| {{cpp|1=R operator -(K a);}}

{{rh}} colspan="2" | Multiplication

| align="center" | a * b

| {{cpp|1=R K::operator *(S b);}}

| {{cpp|1=R operator *(K a, S b);}}

{{rh}} colspan="2" | Division

| align="center" | a / b

| {{cpp|1=R K::operator /(S b);}}

| {{cpp|1=R operator /(K a, S b);}}

{{rh}} colspan="2" | Modulo

| align="center" | a % b

| {{cpp|1=R K::operator %(S b);}}

| {{cpp|1=R operator %(K a, S b);}}

{{rh}} colspan="2" | Prefix increment

| align="center" | ++a

| {{cpp|1=R& K::operator ++();}}

| {{cpp|1=R& operator ++(K& a);}}

{{rh}} colspan="2" | Postfix increment

| align="center" | a++

| {{cpp|1=R K::operator ++(int);}}{{efn|name=dummy-int|The {{cpp|int}} is a dummy parameter to differentiate between prefix and postfix.}}

| {{cpp|1=R operator ++(K& a, int);}}{{efn|name=dummy-int}}

{{rh}} colspan="2" | Prefix decrement

| align="center" | --a

| {{cpp|1=R& K::operator --();}}

| {{cpp|1=R& operator --(K& a);}}

{{rh}} colspan="2" | Postfix decrement

| align="center" | a--

| {{cpp|1=R K::operator --(int);}}{{efn|name=dummy-int}}

| {{cpp|1=R operator --(K& a, int);}}{{efn|name=dummy-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.{{cite web|url=https://en.cppreference.com/w/cpp/language/operators#Comparison_operators|title=Operator overloading§Comparison operators|website=cppreference.com}}

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

{{rh}} colspan="2" | Equal to

| align="center" | a == b

| {{yes}}

| {{cpp|1=bool K::operator ==(S const& b) const;}}

| {{cpp|1=bool operator ==(K const& a, S const& b);}}

{{rh}} colspan="2" | Not equal to

| style="text-align:center;" | a != b

{{yes}}

| {{cpp|1=bool K::operator !=(S const& b) const;}}

| {{cpp|1=bool operator !=(K const& a, S const& b);}}

{{rh}} colspan="2" | Greater than

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

{{yes}}

| {{cpp|1=bool K::operator >(S const& b) const;}}

| {{cpp|1=bool operator >(K const& a, S const& b);}}

{{rh}} colspan="2" | Less than

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

{{yes}}

| {{cpp|1=bool K::operator <(S const& b) const;}}

| {{cpp|1=bool operator <(K const& a, S const& b);}}

{{rh}} colspan="2" | Greater than or equal to

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

{{yes}}

| {{cpp|1=bool K::operator >=(S const& b) const;}}

| {{cpp|1=bool operator >=(K const& a, S const& b);}}

{{rh}} colspan="2" | Less than or equal to

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

{{yes}}

| {{cpp|1=bool K::operator <=(S const& b) const;}}

| {{cpp|1=bool operator <=(K const& a, S const& b);}}

{{rh}} colspan="2" | Three-way comparison{{efn|Possible return types: std::weak_ordering, std::strong_ordering and std::partial_ordering to which they all are convertible to.}}

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

{{no}}

| {{cpp|1=auto K::operator <=>(const S &b);}}

| {{cpp|1=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.{{Cite web|url=https://isocpp.org/wiki/faq/operator-overloading|title=Standard C++}}

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

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

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

in class K

! outside class

{{rh}} colspan="2" | NOT

| align="center" | !a

| {{cpp|1=bool K::operator !();}}

| {{cpp|1=bool operator !(K a);}}

{{rh}} colspan="2" | AND

| style="text-align:center;" | a && b

| {{cpp|1=bool K::operator &&(S b);}}

| {{cpp|1=bool operator &&(K a, S b);}}

{{rh}} colspan="2" | OR

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

b

| {{code|1=bool K::operator {{!!}}(S b);|lang=cpp}}

| {{code|1=bool operator {{!!}}(K a, S b);|lang=cpp}}

=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

{{rh}} colspan="2" | NOT

| align="center" | ~a

| {{cpp|1=R K::operator ~();}}

| {{cpp|1=R operator ~(K a);}}

{{rh}} colspan="2" | AND

| style="text-align:center;" | a & b

| {{cpp|1=R K::operator &(S b);}}

| {{cpp|1=R operator &(K a, S b);}}

{{rh}} colspan="2" | OR

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

| {{cpp|1=R K::operator {{!}}(S b);|lang=cpp}}

| {{cpp|1=R operator {{!}}(K a, S b);|lang=cpp}}

{{rh}} colspan="2" | XOR

| style="text-align:center;" | a ^ b

| {{cpp|1=R K::operator ^(S b);}}

| {{cpp|1=R operator ^(K a, S b);}}

{{rh}} colspan="2" | Shift left

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

| {{cpp|1=R K::operator <<(S b);}}

| {{cpp|1=R operator <<(K a, S b);}}

{{rh}} colspan="2" | Shift right{{Refn | Operation="rightbitshift" | group="lower-alpha" | According to the C99 standard, the right shift of a negative number is implementation defined. Most implementations, e.g., the GCC,{{Citation | contribution = Integers implementation | url = //gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Integers-implementation.html#Integers-implementation | title = GCC 4.3.3 | publisher = GNU}}. use an arithmetic shift (i.e., sign extension), but a logical shift is possible.}}

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

| {{cpp|1=R K::operator >>(S b);}}

| {{cpp|1=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.

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

! rowspan="2" | Operation

! rowspan="2" | Syntax

! colspan="2" | C++ prototype

in class K

! outside class

{{rh}} | Assignment

| style="text-align:center;" | {{nowrap| 1=a = b}}

| {{cpp|1=R& K::operator =(S b);}}

| {{n/a}}

{{rh}} | Addition combination

| align="center" | a += b

| {{cpp|1=R& K::operator +=(S b);}}

| {{cpp|1=R& operator +=(K& a, S b);}}

{{rh}} | Subtraction combination

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

| {{cpp|1=R& K::operator -=(S b);}}

| {{cpp|1=R& operator -=(K& a, S b);}}

{{rh}} | Multiplication combination

| style="text-align:center;" | a *= b

| {{cpp|1=R& K::operator *=(S b);}}

| {{cpp|1=R& operator *=(K& a, S b);}}

{{rh}} | Division combination

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

| {{cpp|1=R& K::operator /=(S b);}}

| {{cpp|1=R& operator /=(K& a, S b);}}

{{rh}} | Modulo combination

| style="text-align:center;" | a %= b

| {{cpp|1=R& K::operator %=(S b);}}

| {{cpp|1=R& operator %=(K& a, S b);}}

{{rh}} | Bitwise AND combination

| style="text-align:center;" | a &= b

| {{cpp|1=R& K::operator &=(S b);}}

| {{cpp|1=R& operator &=(K& a, S b);}}

{{rh}} | Bitwise OR combination

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

| {{cpp|1=R& K::operator {{!}}=(S b);|lang=cpp}}

| {{cpp|1=R& operator {{!}}=(K& a, S b);|lang=cpp}}

{{rh}} | Bitwise XOR combination

| style="text-align:center;" | a ^= b

| {{cpp|1=R& K::operator ^=(S b);}}

| {{cpp|1=R& operator ^=(K& a, S b);}}

{{rh}} | Bitwise left shift combination

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

| {{cpp|1=R& K::operator <<=(S b);}}

| {{cpp|1=R& operator <<=(K& a, S b);}}

{{rh}} | Bitwise right shift combination{{Refn | name="rightbitshift" | group="lower-alpha" | According to the C99 standard, the right shift of a negative number is implementation defined. Most implementations, e.g., the GCC,{{Citation | contribution = Integers implementation | url = //gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Integers-implementation.html#Integers-implementation | title = GCC 4.3.3 | publisher = GNU}}. use an arithmetic shift (i.e., sign extension), but a logical shift is possible.}}

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

| {{cpp|1=R& K::operator >>=(S b);}}

| {{cpp|1=R& operator >>=(K& a, S b);}}

=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

{{rh}} colspan="2" | Subscript

| align="center" | a[b]a<:b:>{{Cite web |title=ISO/IEC 9899:1999 specification, TC3 |url=https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf#%5B%7B%22num%22%3A148%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C-27%2C816%2Cnull%5D |at=p. 64, § 6.4.6 Ponctuators para. 3}}

| {{yes}}

| {{yes}}

| {{cpp|1=R& K::operator [](S b);}}
{{cpp|1=R& K::operator [](S b, ...);}}

| {{n/a}}

{{rh}} colspan="2" | Indirection
{{small|(object pointed to by a)}}

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

{{yes}}{{yes}}

| {{cpp|1=R& K::operator *();}}

| {{cpp|1=R& operator *(K a);}}

{{rh}} colspan="2" | Address-of
{{small|(address of a)}}

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

{{yes}}{{yes}}

| {{cpp|1=R* K::operator &();}}

| {{cpp|1=R* operator &(K a);}}

{{rh}} colspan="2" | Structure dereference
{{small|(member b of object pointed to by a)}}

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

{{yes}}{{yes}}

| {{cpp|1=R* K::operator ->();}}

| {{n/a}}

{{rh}} colspan="2" | Structure reference
{{small|(member b of object a)}}

| style="text-align:center;" | a.b

{{no}}{{yes}}

| {{rh}} colspan="2" {{n/a}}

{{rh}} colspan="2" | Member selected by pointer-to-member b of object pointed to by a

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

{{yes}}{{no}}

| {{cpp|1=R& K::operator ->*(S b);}}

| {{cpp|1=R& operator ->*(K a, S b);}}

{{rh}} colspan="2" | Member of object a selected by pointer-to-member b

| style="text-align:center;" | a.*b

{{no}}{{no}}

| {{rh}} colspan="2" {{n/a}}

=Other=

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

{{rh}} colspan="2" | Function call

| align="center" | a(a1, a2)

| {{yes}}

| {{yes}}

| {{cpp|1=R K::operator ()(S a, T b, ...);}}

| {{n/a}}

{{rh}} colspan="2" | Comma

| style="text-align:center;" | a, b

{{yes}}{{yes}}

| {{cpp|1=R K::operator ,(S b);}}

| {{cpp|1=R operator ,(K a, S b);}}

{{rh}} colspan="2" | Ternary conditional

| style="text-align:center;" | a ? b : c

{{no}}{{yes}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Scope resolution

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

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | User-defined literals

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

{{yes}}{{no}}

| {{n/a}}

| {{cpp|1=R operator "" _b(T a)}}

{{rh}} colspan="2" | Sizeof

| style="text-align:center;" | sizeof a
sizeof (R)

{{no}}{{yes}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Size of parameter pack

| style="text-align:center;" | sizeof...(Args)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Alignof

| style="text-align:center;" | alignof(R)
or _Alignof(R)

{{no}}{{yes}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Decltype

| style="text-align:center;" | decltype (a)
decltype (R)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Type identification

| style="text-align:center;" | typeid(a)
typeid(R)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Conversion
{{small|(C-style cast)}}

| style="text-align:center;" | (R)a

{{yes}}{{yes}}

| {{cpp|1=K::operator R();}}{{cite web|url=https://en.cppreference.com/w/cpp/language/cast_operator|title=user-defined conversion|access-date=5 April 2020}}

| {{n/a}}

{{rh}} colspan="2" | Conversion{{efn|Behaves like const_cast/static_cast/reinterpret_cast. In the last two cases, the auto specifier is replaced with the type of the invented variable x declared with auto x(a); (which is never interpreted as a function declaration) or auto x{a};, respectively.}}[https://en.cppreference.com/w/cpp/language/explicit_cast Explicit type conversion] in C++

| style="text-align:center;" | R(a)
R{a}
auto(a)
auto{a}

{{no}}{{no}}

| {{rh}} colspan="2" {{n/a}}

{{rh}} colspan="2" | static_cast conversion{{efn|For user-defined conversions, the return type implicitly and necessarily matches the operator name unless the type is inferred (e.g. {{cpp|1=operator auto()}}, {{cpp|1=operator decltype(auto)()}} etc.).}}

| style="text-align:center;" | static_cast(a)

{{yes}}{{no}}

| {{cpp|1=K::operator R();}}
{{cpp|1=explicit K::operator R();}}

| {{n/a}}

{{rh}} colspan="2" | dynamic cast conversion

| style="text-align:center;" | dynamic_cast(a)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | const_cast conversion

| style="text-align:center;" | const_cast(a)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | reinterpret_cast conversion

| style="text-align:center;" | reinterpret_cast(a)

{{no}}{{no}}

| colspan="2" {{n/a}}

{{rh}} colspan="2" | Allocate storage

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

{{yes}}{{no}}

| {{cpp|1=void* K::operator new(size_t x);}}

| {{cpp|1=void* operator new(size_t x);}}

{{rh}} colspan="2" | Allocate array

| style="text-align:center;" | new R[n]

{{yes}}{{no}}

| {{cpp|1=void* K::operator new[](size_t a);}}

| {{cpp|1=void* operator new[](size_t a);}}

{{rh}} colspan="2" | Deallocate storage

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

{{yes}}{{no}}

| {{cpp|1=void K::operator delete(void* a);}}

| {{cpp|1=void operator delete(void* a);}}

{{rh}} colspan="2" | Deallocate array

| style="text-align:center;" | delete[] a

{{yes}}{{no}}

| {{cpp|1=void K::operator delete[](void* a);}}

| {{cpp|1=void operator delete[](void* a);}}

{{rh}} colspan="2" | Exception check

| style="text-align:center;" | noexcept(a)

{{no}}{{no}}

| colspan="2" {{n/a}}

= Synonyms =

C++ defines keywords to act as aliases for a number of operators:{{cite book | title = ISO/IEC 14882:1998(E) Programming Language C++ | date = 1 September 1998 | publisher = open-std.org – The C++ Standards Committee | pages = 40–41}}

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

! Keyword

Operator
{{code|and}}&&
{{code|and_eq}}&=
{{code|bitand}}&
{{code|bitor}}|
{{code|compl}}~
{{code|not}}!
{{code|not_eq}}!=
{{code|or}}||
{{code|or_eq}}|=
{{code|xor}}^
{{code|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, {{code|1=(a > 0 and not flag)}} and {{code|1=(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., {{code|1=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 {{code|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).{{cite book | title = ISO/IEC 9899:201x Programming Languages - C | date = 19 December 2011 | publisher = open-std.org – The C Standards Committee | pages = 465}}{{cite tech report |title=the ISO C 1999 standard, section 6.5.6 note 71 |institution=ISO |year=1999 }}{{cite web |title=C++ Built-in Operators, Precedence and Associativity |url=https://docs.microsoft.com/en-US/cpp/cpp/cpp-built-in-operators-precedence-and-associativity |website=docs.microsoft.com |access-date=11 May 2020 |language=en-us}}

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

highest

| ::

| Scope resolution (C++ only)

| None

rowspan=11| 2

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

| 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" | --

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

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

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

style="border-bottom-style: none; border-top-style: none" | []

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

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

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

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

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

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

| 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" | const_cast

| 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" | dynamic_cast

| 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" | reinterpret_cast

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

style="border-top-style: none" | static_cast

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

rowspan="13" | 3

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

| 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" | --

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

style="border-bottom-style: none; border-top-style: none" | new, new[]

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

style="border-top-style: none" | delete, delete[]

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

rowspan=2| 4

| style="border-bottom-style: none" | .*

| 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" | ->*

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

rowspan=3| 5

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

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

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

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

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

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

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

rowspan=2| 6

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

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

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

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

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

rowspan=2| 7

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

| 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" | >>

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

rowspan=1| 8

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

| 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" | <

| 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" | <=

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

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

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

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

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

rowspan=2| 10

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

| 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" | !=

| style="border-bottom-style: none; border-top-style: none" | 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

rowspan="2" | 16

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

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

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

style="border-top-style: none" | co_yield
rowspan="13" | 17

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

style="border-top-style: none" | throw

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

Image:Precedence 2.png

  • 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.{{cite web |title=C Operator Precedence - cppreference.com |url=https://en.cppreference.com/w/c/language/operator_precedence |website=en.cppreference.com |access-date=10 April 2020}}{{Cite web|url=https://stackoverflow.com/questions/13515434/does-the-c-c-ternary-operator-actually-have-the-same-precedence-as-assignment/13515505|title=Does the C/C++ ternary operator actually have the same precedence as assignment operators?|website=Stack Overflow|access-date=2019-09-22}}

To use the comma operator in a function call argument expression, variable assignment, or a comma-separated list, use of parentheses is required.{{cite web |title=Other operators - cppreference.com |url=https://en.cppreference.com/w/c/language/operator_other |website=en.cppreference.com |access-date=10 April 2020}}{{cite web |title=c++ - How does the Comma Operator work |url=https://stackoverflow.com/questions/54142/how-does-the-comma-operator-work/ |website=Stack Overflow |access-date=1 April 2020}} 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.{{Citation | url = https://www.bell-labs.com/usr/dmr/www/chist.html | title = C history § Neonatal C| publisher = Bell labs}}. Conceptually, & and | are arithmetic operators like * and +.

The expression {{cpp|1=a & b == 7}} is syntactically parsed as {{cpp|1=a & (b == 7)}} whereas the expression {{cpp |1=a + b == 7}} is parsed as {{cpp|1=(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 {{cpp|&& {{!!}}}} didn't exist. Instead {{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 {{cpp|1= if (a==b & c) {...} }} it behaved as a logical operator, but in {{cpp|1= c = a & b}} it behaved as a bitwise one). It was retained so as to keep backward compatibility with existing installations.{{cite web|url=https://www.perlmonks.org/?node_id=1159769|title=Re^10: next unless condition|website=www.perlmonks.org|access-date=23 March 2018}}

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

{{reflist |group="lower-alpha"|refs=

since C++11

since C++23

The modulus operator only supports integer operands; for floating point, a function such as math.h can be used.

In the context of iostreams in C++, writers often will refer to {{cpp|<<}} and {{cpp|>>}} as the "put-to" or "stream insertion" and "get-from" or "stream extraction" operators, respectively.

The actual address of an object with an overloaded operator & can be obtained with [https://en.cppreference.com/w/cpp/memory/addressof std::addressof]

The return type of {{cpp|operator->()}} must be a type for which the {{cpp |->}} operation can be applied, such as a pointer type. If {{cpp|x}} is of type {{cpp |C}} where {{cpp |C}} overloads {{cpp|operator->()}}, {{cpp|x->y}} gets expanded to {{cpp|x.operator->()->y}}.

{{Citation | publisher = Aristeia | url = http://aristeia.com/Papers/DDJ_Oct_1999.pdf | title = Implementing operator->* for Smart Pointers | first = Scott | last = Meyers | journal = Dr. Dobb's Journal |date=Oct 1999}}.

Although a :: punctuator exists in C as of C23, it is not used as a scope resolution operator.

About [http://en.cppreference.com/w/cpp/language/user_literal C++11 User-defined literals]

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.{{Citation needed|date=July 2024}}

C++ defines alignof operator, whereas C defines _Alignof (C23 defines both). Both operators have the same semantics.

About [https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison C++20 three-way comparison]

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.

}}

See also

  • {{Annotated link|Bitwise operations in C}}
  • {{Annotated link|Bit manipulation}}
  • {{Annotated link|Logical operator}}
  • {{Annotated link|Boolean algebra (logic)}}
  • {{Annotated link|Table of logic symbols}}

References

{{Reflist|30em}}