Content deleted Content added
Stevebroshar (talk | contribs) →Logical operators: Re-word for clarity/readability |
Voltaic181 (talk | contribs) m →Relational: Fixed table spanning incorrectly. |
||
(40 intermediate revisions by 4 users not shown) | |||
Line 7:
When not overloaded, for the operators <code>&&</code>, <code>||</code>, and <code>,</code> (the [[comma operator]]), there is a [[sequence point]] after the evaluation of the first operand.
Most of the operators available in C and C++ are also available in other [[C-family]] languages such as [[C Sharp (programming language)|C#]], [[D (programming language)|D]], [[Java (programming language)|Java]], [[Perl]], and [[PHP]] with the same precedence, associativity, and semantics.
Many operators specified by a sequence of symbols are commonly referred to by a name that consists of the name of each symbol. For example, <code>+=</code> and <code>-=</code> are often called "plus equal(s)" and "minus equal(s)", instead of the more verbose "assignment by addition" and "assignment by subtraction".
==Operators==
In the following tables, lower case letters such as <code>a</code> and <code>b</code> represent literal values, object/variable names, or l-values, as appropriate. <code>R</code>, <code>S</code> and <code>T</code> stand for a data type, and <code>K</code> for a class or enumeration type. Some operators have alternative spellings using [[digraphs and trigraphs (programming)|digraphs and trigraphs]] or [[#
===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" |
! rowspan="2" | Syntax
! colspan="2" | C++ prototype
Line 28:
|-
| {{rh}} colspan="2" | [[Addition]]
|
| {{cpp|1=R K::operator +(S b);}}
| {{cpp|1=R operator +(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Subtraction]]
|
| {{cpp|1=R K::operator -(S b);}}
| {{cpp|1=R operator -(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Unary operation|Unary]] plus;
|
| {{cpp|1=R K::operator +();}}
| {{cpp|1=R operator +(K a);}}
|-
| {{rh}} colspan="2" | [[Unary operation|Unary]] minus;
|
| {{cpp|1=R K::operator -();}}
| {{cpp|1=R operator -(K a);}}
|-
| {{rh}} colspan="2" | [[Multiplication]]
|
| {{cpp|1=R K::operator *(S b);}}
| {{cpp|1=R operator *(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Division (mathematics)|Division]]
|
| {{cpp|1=R K::operator /(S b);}}
| {{cpp|1=R operator /(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Modulo operation|Modulo]]
|
| {{cpp|1=R K::operator %(S b);}}
| {{cpp|1=R operator %(K a, S b);}}
|-
|
| align="center" | <code>'''++'''a</code>
| {{cpp|1=R& K::operator ++();}}
|-
| {{rh}}
|
| {{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
| align="center" | <code>'''--'''a</code>
| {{cpp|1=R& K::operator --();}}
| {{cpp|1=R& operator --(K& a);}}
|-
| {{rh}}
|
| {{cpp|1=R K::operator --(int);}}{{efn|name=dummy-int}}
| {{cpp|1=R operator --(K& a, int);}}{{efn|name=dummy-int}}
|}
===Relational
All [[Relational operator|relational]] (comparison) operators can be overloaded in C++. Since [[C++20]], the inequality operator is automatically generated if <code>operator==</code> is defined and all four relational operators are automatically generated if <code>operator<=></code> is defined.<ref>{{cite web|url=https://en.cppreference.com/w/cpp/language/operators#Comparison_operators|title=Operator overloading§Comparison operators|website=cppreference.com}}</ref>
{| class="wikitable" style="width:100%"
! colspan="2" rowspan="2" |
! rowspan="2" | Syntax
! rowspan="2" | In C
Line 102 ⟶ 96:
! outside class
|-
|
|
|
|
|
|-
| {{rh}} colspan="2" | Not equal to
Line 133 ⟶ 127:
| {{cpp|1=bool operator <=(K const& a, S const& b);}}
|-
| {{rh}} colspan
|
| {{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++.
Line 148 ⟶ 140:
{| class="wikitable" style="width:100%"
! colspan="2" rowspan="2" |
! rowspan="2" | Syntax
! colspan="2" | C++ prototype
Line 155 ⟶ 147:
! outside class
|-
|
|
|
|
|-
| {{rh}} colspan="2" | [[Logical conjunction|
| style="text-align:center;" | <code>a '''&&''' b</code>
| {{cpp|1=bool K::operator &&(S b);}}
| {{cpp|1=bool operator &&(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Logical disjunction|
| style="text-align:center;" | <code>a '''<nowiki>||</nowiki>''' b</code>
| {{code|1=bool K::operator {{!!}}(S b);|lang=cpp}}
Line 171 ⟶ 163:
|}
===Bitwise
{| class="wikitable" style="width:100%"
! colspan="2" rowspan="2" |
! rowspan="2" | Syntax
! colspan="2" | C++ prototype
Line 183 ⟶ 175:
! outside class
|-
|
|
|
|
|-
| {{rh}} colspan="2" | [[Bitwise operation#AND|
| style="text-align:center;" | <code>a '''&''' b</code>
| {{cpp|1=R K::operator &(S b);}}
| {{cpp|1=R operator &(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Bitwise operation#OR|
| style="text-align:center;" | <code>a '''<nowiki>|</nowiki>''' b</code>
| {{cpp|1=R K::operator {{!}}(S b);|lang=cpp}}
| {{cpp|1=R operator {{!}}(K a, S b);|lang=cpp}}
|-
| {{rh}} colspan="2" | [[Bitwise operation#XOR|
| style="text-align:center;" | <code>a '''^''' b</code>
| {{cpp|1=R K::operator ^(S b);}}
| {{cpp|1=R operator ^(K a, S b);}}
|-
| {{rh}} colspan="2" | [[Bitwise shift|
| style="text-align:center;" | <code>a '''<<''' b</code>
| {{cpp|1=R K::operator <<(S b);}}
| {{cpp|1=R operator <<(K a, S b);}}
|-
| {{rh}} colspan="2" |
| style="text-align:center;" | <code>a '''>>''' b</code>
| {{cpp|1=R K::operator >>(S b);}}
Line 214 ⟶ 206:
|}
===Assignment
For the
{| class="wikitable" style="width:100%"
! rowspan="2" |
! rowspan="2" | Syntax
! colspan="2" | C++ prototype
Line 228 ⟶ 220:
! outside class
|-
! {{rh}} | [[Assignment operator
| style="text-align:center;" | {{nowrap| 1=<code>a '''=''' b</code>}}
| {{cpp|1=R& K::operator =(S b);}}
| {{n/a}}
|-
! {{rh}} | Addition
| align="center" | <code>a '''+=''' b</code>
| {{cpp|1=R& K::operator +=(S b);}}
| {{cpp|1=R& operator +=(K& a, S b);}}
|-
! {{rh}} | Subtraction
| style="text-align:center;" | <code>a '''-=''' b</code>
| {{cpp|1=R& K::operator -=(S b);}}
| {{cpp|1=R& operator -=(K& a, S b);}}
|-
! {{rh}} | Multiplication
| style="text-align:center;" | <code>a '''*=''' b</code>
| {{cpp|1=R& K::operator *=(S b);}}
| {{cpp|1=R& operator *=(K& a, S b);}}
|-
! {{rh}} | Division
| style="text-align:center;" | <code>a '''/=''' b</code>
| {{cpp|1=R& K::operator /=(S b);}}
| {{cpp|1=R& operator /=(K& a, S b);}}
|-
! {{rh}} | Modulo
| style="text-align:center;" | <code>a '''%=''' b</code>
| {{cpp|1=R& K::operator %=(S b);}}
| {{cpp|1=R& operator %=(K& a, S b);}}
|-
! {{rh}} | Bitwise AND
| style="text-align:center;" | <code>a '''&=''' b</code>
| {{cpp|1=R& K::operator &=(S b);}}
| {{cpp|1=R& operator &=(K& a, S b);}}
|-
! {{rh}} | Bitwise OR
| style="text-align:center;" | <code>a '''<nowiki>|</nowiki>=''' b</code>
| {{cpp|1=R& K::operator {{!}}=(S b);|lang=cpp}}
| {{cpp|1=R& operator {{!}}=(K& a, S b);|lang=cpp}}
|-
! {{rh}} | Bitwise XOR
| style="text-align:center;" | <code>a '''^=''' b</code>
| {{cpp|1=R& K::operator ^=(S b);}}
| {{cpp|1=R& operator ^=(K& a, S b);}}
|-
! {{rh}} | Bitwise left shift
| style="text-align:center;" | <code>a '''<<=''' b</code>
| {{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,<ref name="Integers">{{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}}.</ref> use an [[arithmetic shift]] (i.e., sign extension), but a [[logical shift]] is possible.}}
| style="text-align:center;" | <code>a '''>>=''' b</code>
| {{cpp|1=R& K::operator >>=(S b);}}
Line 284 ⟶ 276:
|}
===Member and pointer
{| class="wikitable" style="width:100%"
! colspan="2" rowspan="2" |
! rowspan="2" | Syntax
! rowspan="2" | Can overload
! rowspan="2" | In C
! colspan="2" | C++ prototype
Line 295 ⟶ 287:
! outside class
|-
|
|
|
|
| {{cpp|1=R& K::operator [](S b);}}<br/>{{cpp|1=R& K::operator [](S b, ...);
|
|-
| {{rh}} colspan="2" | Indirection <br>{{small|(
| style="text-align:center;" | <code>'''*'''a</code> || {{yes}} || {{yes}}
| {{cpp|1=R& K::operator *();}}
| {{cpp|1=R& operator *(K a);}}
|-
| {{rh}} colspan="2" | Address-of <br>{{small|(
| style="text-align:center;" | <code>'''&'''a</code> || {{yes}}<ref name="addressof2" group="lower-alpha"/> || {{yes}}
| {{cpp|1=R* K::operator &();}}
| {{cpp|1=R* operator &(K a);}}
|-
| {{rh}} colspan="2" | Structure dereference <br>{{small|(
| style="text-align:center;" | <code>a'''->'''b</code> || {{yes}} || {{yes}}
| {{cpp|1=R* K::operator ->();}}<ref name="arrowptr" group="lower-alpha" /><br />
| {{n/a}}
|-
| {{rh}} colspan="2" | Structure reference <br>{{small|(
| style="text-align:center;" | <code>a'''.'''b</code> || {{no}} || {{yes}}
| {{rh}} colspan="2" {{n/a}}
Line 331 ⟶ 323:
|}
===Other
{| class="wikitable" style="width:100%"
! colspan="2" rowspan="2" |
! rowspan="2" | Syntax
! rowspan="2" | Can overload
! rowspan="2" | In C
! colspan="2" | C++ prototype
Line 342 ⟶ 334:
! outside class
|-
|
|
|
|
| {{cpp|1=R K::operator ()(S a, T b, ...);}}<!--
|
|-
| {{rh}} colspan="2" | [[comma operator|Comma]]
Line 362 ⟶ 354:
| colspan="2" {{n/a}}
|-
| {{rh}} colspan="2" | User-defined literals<ref name="ud-literal" group="lower-alpha" /><
| style="text-align: center;" | <code><nowiki>"a"_b</nowiki></code> || {{yes}} || {{no}}
| {{n/a}}
Line 371 ⟶ 363:
| colspan="2" {{n/a}}
|-
| {{rh}} colspan="2" | Size of [[variadic template|parameter pack]]<
| style="text-align:center;" | <code>'''sizeof...'''(Args)</code> || {{no}} || {{no}}
| colspan="2" {{n/a}}
|-
| {{rh}} colspan="2" |
| style="text-align:center;" | <code>'''alignof'''(R)</code> <br> or <code>'''_Alignof'''(R)</code><ref name="alignof" group="lower-alpha"/> || {{no}} || {{yes}}
| colspan="2" {{n/a}}
|-
| {{rh}} colspan="2" | [[Decltype]]<
| style="text-align:center;" | <code>'''decltype''' (a)</code><br/><code>'''decltype''' (R)</code> || {{no}} || {{no}}
| colspan="2" {{n/a}}
Line 387 ⟶ 379:
| colspan="2" {{n/a}}
|-
| {{rh}} colspan="2" | [[type conversion|Conversion]]
| style="text-align:center;" | <code>(R)a</code> || {{yes}} || {{yes}}
| {{cpp|1=K::operator R();}}<ref>{{cite web|url=https://en.cppreference.com/w/cpp/language/cast_operator|title=user-defined conversion|access-date=5 April 2020}}</ref>
| {{n/a}}
|-
| {{rh}} colspan="2" | [[type conversion|Conversion]]{{efn|Behaves like const_cast/static_cast/reinterpret_cast. In the last two cases, the <code>auto</code> specifier is replaced with the type of the invented variable x declared with <code>auto x(a);</code> (which is never interpreted as a function declaration) or <code>auto x{a};</code>, respectively.}}<ref>[https://en.cppreference.com/w/cpp/language/explicit_cast Explicit type conversion] in C++</ref>
| style="text-align:center;" | <code>R(a)</code><br><code>R{a}</code><
| {{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.).}}
|
| {{cpp|1=K::operator R();}}<br>{{cpp|1=explicit K::operator R();}}<ref
| {{n/a}}
|-
| {{rh}} colspan="2" | [[dynamic cast]] conversion
Line 420 ⟶ 410:
| {{cpp|1=void* operator new(size_t x);}}
|-
| {{rh}} colspan="2" | Allocate
| style="text-align:center;" | <code>'''new''' R'''['''n''']'''</code><ref name="infer2" group="lower-alpha"/> || {{yes}} || {{no}}
| {{cpp|1=void* K::operator new[](size_t a);}}
Line 430 ⟶ 420:
| {{cpp|1=void operator delete(void* a);}}
|-
| {{rh}} colspan="2" | Deallocate
| style="text-align:center;" | <code>'''delete[]''' a</code> || {{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;" | <code>'''noexcept'''(a)</code> || {{no}} || {{no}}
| colspan="2" {{n/a}}
|}
=== Synonyms ===
C++ defines keywords to act as aliases for a number of operators:<ref name="Committee">{{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}}</ref>
{| class="wikitable" style="width:30%; text-align:center;"
! Keyword || Operator
|-
| {{code|and}} || <code>&&</code>
|-
| {{code|and_eq}} || <code>&=</code>
|-
| {{code|bitand}} || <code>&</code>
|-
| {{code|bitor}} || <code>|</code>
|-
| {{code|compl}} || <code>~</code>
|-
| {{code|not}} || <code>!</code>
|-
| {{code|not_eq}} || <code>!=</code>
|-
| {{code|or}} || <code>||</code>
|-
| {{code|or_eq}} || <code>|=</code>
|-
| {{code|xor}} || <code>^</code>
|-
| {{code|xor_eq}} || <code>^=</code>
|}
Each keyword is a different way to specify an operator and as such can be used instead of the corresponding symbolic variation. For example, {{code|1=(a > 0 and not flag)}} and {{code|1=(a > 0 && !flag)}} specify the same behavior. As another example, the <code>bitand</code> keyword may be used to replace not only the ''bitwise-and'' operator but also the ''address-of'' operator, and it can be used to specify reference types (e.g., {{code|1=int bitand ref = n}}).
The ISO C specification makes allowance for these keywords as preprocessor macros in the header file [[iso646.h|{{code|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|{{code|ciso646}}]] which had no effect as well.
==Expression evaluation order==
During expression evaluation, the order in which sub-expressions are evaluated is determined by [[order of operations|precedence]] and [[operator associativity|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>{{cite book | title = ISO/IEC 9899:201x Programming Languages - C | date = 19 December 2011 | publisher = open-std.org – The C Standards Committee | pages = 465}}</ref><ref>{{cite tech report |title=the ISO C 1999 standard, section 6.5.6 note 71 |institution=ISO |year=1999 }}</ref><ref>{{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}}</ref>
Operator precedence is not affected by overloading.
{| class="wikitable"
|-
! style="text-align: left" |
! style="text-align: left" | Operator
! style="text-align: left" | Description
Line 696 ⟶ 697:
| Left-to-right
|}
===
Although this table is adequate for describing most evaluation order, it does not describe a few details. The [[ternary operator]] allows any arbitrary expression as its middle operand, despite being listed as having higher precedence than the assignment and comma operators. Thus <code>a ? b, c : d</code> is interpreted as <code>a ? (b, c) : d</code>, and not as the meaningless <code>(a ? b), (c : d)</code>. So, the expression in the middle of the conditional operator (between <code>'''?'''</code> and <code>''':'''</code>) is parsed as if parenthesized. Also, the immediate, un-parenthesized result of a C cast expression cannot be the operand of <code>sizeof</code>. Therefore, <code>sizeof (int) * x</code> is interpreted as <code>(sizeof(int)) * x</code> and not <code>sizeof ((int) * x)</code>.
===Chained expressions===
The precedence table determines the order of binding in chained expressions, when it is not expressly specified by parentheses.
* For example, <code>++x*3</code> is ambiguous without some precedence rule(s). The precedence table tells us that: {{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 <code>x*3</code>); it is equivalent to (<code>++x</code>, <code>x*3</code>).
Line 705 ⟶ 708:
* 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
<syntaxhighlight lang="c">logical-OR-expression ? expression : conditional-expression</syntaxhighlight>
while in C++ it is:
Line 718 ⟶ 721:
which is a valid expression.<ref>{{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}}</ref><ref>{{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}}</ref>
<syntaxhighlight lang="cpp"> int a = 1, b = 2, weirdVariable = (++a, b), d = 4; </syntaxhighlight> ===Criticism of bitwise and equality operators precedence===
Line 729 ⟶ 736:
Moreover, in C++ (and later versions of C) equality operations, with the exception of the three-way comparison operator, yield [[Boolean data type|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=
<ref name="sinceCXX11" group="lower-alpha">since C++11</ref>
<ref name="sinceCXX23" group="lower-alpha">since C++23</ref>
<ref name="modulo" group="lower-alpha">The modulus operator only supports integer operands; for floating point, a function such as [[math.h|{{code|fmod|cpp}}]] can be used.</ref>
<ref name="bitshift" group="lower-alpha">In the context of [[iostream]]s 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.</ref>
<ref name="addressof2" group="lower-alpha">The actual address of an object with an overloaded <code>operator &</code> can be obtained with [https://en.cppreference.com/w/cpp/memory/addressof <code>std::addressof</code>]</ref>
<ref name="arrowptr" group="lower-alpha">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}}.</ref>
<ref name="arrowstar" group= "lower-alpha">{{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}}.</ref>
<ref name="scopal" group="lower-alpha">Although a <code>::</code> punctuator exists in C as of C23, it is not used as a scope resolution operator.</ref>
<ref name="ud-literal" group="lower-alpha">About [http://en.cppreference.com/w/cpp/language/user_literal C++11 User-defined literals]</ref>
<ref name="sizeof" group="lower-alpha">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}}</ref>
<ref name="alignof" group = "lower-alpha">C++ defines <code>alignof</code> operator, whereas C defines <code>_Alignof</code> (C23 defines both). Both operators have the same semantics.</ref>
<ref name="threewaycomparison" group="lower-alpha">About [https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison C++20 three-way comparison]</ref>
<ref name="infer" group="lower-alpha">The type name can also be inferred (e.g <code>new auto</code>) if an initializer is provided.</ref>
<ref name="infer2" group="lower-alpha">The array size can also be inferred if an initializer is provided.</ref>
}}
==See also==
*
*
*
*
*
== References ==
|