In theC andC++ programming languages, thecomma operator (represented by thetoken,) is abinary operator that evaluates its firstoperand and discards the result, and then evaluates the second operand and returns this value (and type). There is asequence point between these evaluations.
The use of the comma token as anoperator is distinct from its use infunction calls and definitions, variable declarations, enum declarations, and similar constructs, where it acts as aseparator.
The comma operator separatesexpressions (which have value) in a way analogous to how thesemicolon terminatesstatements, and sequences of expressions are enclosed in parentheses analogously to how sequences of statements are enclosed in braces:[1](a, b, c) is a sequence of expressions, separated by commas, which evaluates to the last expressionc, while{a; b; c;} is a sequence of statements, and does not evaluate to any value. A comma can only occur between two expressions – commasseparate expressions – unlike the semicolon, which occurs at the end of a (non-block) statement – semicolonsterminate statements.
The comma operator has the lowestprecedence of any C operator, and acts as asequence point. In a combination of commas and semicolons, semicolons have lower precedence than commas, as semicolons separate statements but commas occur within statements, which accords with their use as ordinary punctuation:a, b; c, d is grouped as(a, b); (c, d) because these are two separate statements.
The comma operator has beendeprecated in subscripting expressions (as ofC++20);[2] to reduce confusion, and open up the future possibility of repurposing the syntax for multidimensional array indexing. InC++23, the ability to overloadoperator[] with multiple arguments was added making unparenthesised comma expressions unusable in subscripts.[3] The comma operator is still usable and not deprecated in this context if the comma expression is surrounded by parentheses (as ina[(b,c)]).
| Example | Return value | Behavior |
|---|---|---|
inta=1,b=2;intr=(a,b);returnr; | 2 | During initialization the comma acts as a separator, but in the second line it is an operator. The parentheses are required. Without them the second line would be equivalent tointr=a;intb, which results inb being defined twice, which is illegal. |
inta=1,b=2;intr=(a+=2,a+b);returnr; | 5 | sincea+=2 is evaluated beforea+b is evaluated and assigned tor. |
return(1,2); | 2 | The comma is an operator, not a separator, sincereturn is a keyword and does not act as a function. |
The comma operator has relatively limited use cases. Because it discards its first operand, it is generally only useful where the first operand has desirableside effects that must besequenced before the second operand. Further, because it is rarely used outside of specific idioms, and easily mistaken with other commas or the semicolon, it is potentially confusing and error-prone. Nevertheless, there are certain circumstances where it is commonly used, notably in for loops and inSFINAE.[4] For embedded systems which may have limiteddebugging capabilities, the comma operator can be used in combination with a macro to seamlessly override a function call, to insert code just before the function call.
The comma operator allows multipleassignment statements without using a block statement, for example in the initialization and the increment expressions of afor loop. In the following example, the order of the loop's initializers is significant:
voidrev(char*s,size_tlen){char*first;for(first=s,s+=len;s>=first;--s){putchar(*s);}}
An alternative solution to this problem in other languages isparallel assignment, which allows multiple assignments to occur within a single statement, and also uses a comma, though with different syntax and semantics. This is used inGo in its analogous for loop.[5]
The comma can be used in preprocessor macros to perform multiple operations in the space of a single syntactic expression.
One common use is to provide custom error messages in failed assertions. This is done by passing a parenthesized expression list to theassert macro, where the first expression is an error string and the second expression is the condition being asserted. Theassert macro outputs its argument verbatim on an assertion failure. The following is an example:
#include<assert.h>#include<stdio.h>intmain(void){for(inti=0;i<=9;i++){assert(("i is too big!",i<=4));printf("i = %i\n",i);}return0;}
Output:
i = 0i = 1i = 2i = 3i = 4assert: assert.c:6: test_assert: Assertion `("i is too big!", i <= 4)' failed.Aborted
However the assert macro is usually disabled in production code, so use it only for debug purposes.
The comma can be used within a condition (of an if, while, do while, or for) to allow auxiliary computations, particularly calling a function and using the result, withblock scoping:
if(y=f(x),y>x){...// statements involving x and y}
A similar idiom exists inGo, where the syntax of the if statement explicitly allows an optional statement.[6]
The comma can be used in return statements, to assign to aglobal variable or out parameter (passed by reference). This idiom suggests that the assignments are part of the return, rather than auxiliary assignments in a block that terminates with the actual return. For example, in setting a global error number:
if(failure)return(errno=EINVAL,-1);
This can also be written as:
if(failure){errno=EINVAL;return-1;}
For brevity, the comma can be used to avoid a block and associated braces, as in:
if(x==1)y=2,z=3;
instead of:
if(x==1){y=2;z=3;}
In theOCaml andRuby programming languages, the semicolon (";") is used for this purpose.
JavaScript,[7]Perl[8] andD[9] utilize the comma operator in the same way C/C++ does.
Some other languages with C-like syntax, such asJava[10] andC#, do not have this feature, though C# supports a comma-separated list of expressions in the initializer and iterator of afor statement,[11] thus enabling an equivalent of this in this specific context.
Two expressions separated by a comma are evaluated left to right. The left operand is always evaluated, and all side effects are completed before the right operand is evaluated.
You can use the comma operator when you want to include multiple expressions in a location that requires a single expression.