Take care to notice that the comma operator may be overloaded in C++. The actual behaviour may thus be very different from the one expected.
As an example, Boost.Spirit uses the comma operator quite cleverly to implement list initializers for symbol tables. Thus, it makes the following syntax possible and meaningful:
keywords = "and", "or", "not", "xor";
Notice that due to operator precedence, the code is (intentionally!) identical to
(((keywords = "and"), "or"), "not"), "xor";
That is, the first operator called is keywords.operator =("and")
which returns a proxy object on which the remaining operator,
s are invoked:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
The comma operator has the lowest precedence of all C/C++ operators. Therefore it's always the last one to bind to an expression, meaning this:
a = b, c;
is equivalent to:
(a = b), c;
Another interesting fact is that the comma operator introduces a sequence point. This means that the expression:
a+b, c(), d
is guaranteed to have its three subexpressions (a+b, c() and d) evaluated in order. This is significant if they have side-effects. Normally compilers are allowed to evaluate subexpressions in whatever order they find fit; for example, in a function call:
someFunc(arg1, arg2, arg3)
arguments can be evaluated in an arbitrary order. Note that the commas in the function call are not operators; they are separators.
It would be equal to b
.
The comma operator has a lower precedence than assignment.
The comma operator:
A default version of comma operator is defined for all types (built-in and custom), and it works as follows - given exprA , exprB
:
exprA
is evaluatedexprA
is ignoredexprB
is evaluatedexprB
is returned as the result of the whole expressionWith most operators, the compiler is allowed to choose the order of execution and it is even required to skip the execution whatsoever if it does not affect the final result (e.g. false && foo()
will skip the call to foo
). This is however not the case for comma operator and the above steps will always happen*.
In practice, the default comma operator works almost the same way as a semicolon. The difference is that two expressions separated by a semicolon form two separate statements, while comma-separation keeps all as a single expression. This is why comma operator is sometimes used in the following scenarios:
if( HERE )
for
loop for ( HERE ; ; )
if (foo) HERE ;
(please don't do that, it's really ugly!)When a statement is not an expression, semicolon cannot be replaced by a comma. For example these are disallowed:
(foo, if (foo) bar)
(if
is not an expression)In your case we have:
a=b, c;
, equivalent to a=b; c;
, assuming that a
is of type that does not overload the comma operator.a = b, c = d;
equivalent to a=b; c=d;
, assuming that a
is of type that does not overload the comma operator.Do note that not every comma is actually a comma operator. Some commas which have a completely different meaning:
int a, b;
--- variable declaration list is comma separated, but these are not comma operatorsint a=5, b=3;
--- this is also a comma separated variable declaration listfoo(x,y)
--- comma-separated argument list. In fact, x
and y
can be evaluated in any order!FOO(x,y)
--- comma-separated macro argument listfoo<a,b>
--- comma-separated template argument listint foo(int a, int b)
--- comma-separated parameter listFoo::Foo() : a(5), b(3) {}
--- comma-separated initializer list in a class constructor* This is not entirely true if you apply optimizations. If the compiler recognizes that certain piece of code has absolutely no impact on the rest, it will remove the unnecessary statements.
Further reading: http://en.wikipedia.org/wiki/Comma_operator
The value of a
will be b
, but the value of the expression will be c
. That is, in
d = (a = b, c);
a
would be equal to b
, and d
would be equal to c
.
b's value will be assigned to a. Nothing will happen to c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With