19

I've just come across code that essentially does the following:

int a = (1, 2, 3);

I've never seen this notation before. What does it mean?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Amr Bekhit
  • 4,613
  • 8
  • 34
  • 56
  • 12
    waste of typing code that is. 3 is assigned to a. – Koushik Shetty May 15 '13 at 10:58
  • I wonder though when somebody digs out a duplicate for this (since I cannot believe there is none). – Christian Rau May 15 '13 at 11:03
  • 1
    @ChristianRau, it's very likely there is one - but I actually struggled to construct a search query in google and StackOverflow that returned meaningful results, because I don't know the name of the operator! – Amr Bekhit May 15 '13 at 11:16
  • 6
    [L1](http://stackoverflow.com/questions/14911528/please-explain-comma-operator-in-this-program), [L2](http://stackoverflow.com/questions/1613230/uses-of-c-comma-operator), [L3](http://stackoverflow.com/questions/12959415/comma-operator-in-conditon-of-loop-in-c)..and many more:-) and wow 11 and increasing upvotes:-) – Koushik Shetty May 15 '13 at 11:19
  • 4
    When I asked an easy question yesterday I got a barrage of downvotes!!God can be so unfair!! – Thokchom May 15 '13 at 11:20
  • You may like to read question too: [C: explain if(exit(0),0){} line of code](http://stackoverflow.com/questions/15302789/c-explain-ifexit0-0-line-of-code/15303040#15303040) – Grijesh Chauhan May 15 '13 at 11:24
  • 3
    18 upvotes for something that is a duplicate of probably hundreds of other questions... Hmmm... – JeremyP May 15 '13 at 11:42
  • I know a guy who likes to write code like if( p = foo(), !p ) – brian beuning May 15 '13 at 11:47
  • 4
    If you don't actually know it's called the comma operator, then it's hard to search for it in Google/SO. So, you have to try and describe the syntax in your search query. Even though this question is indeed a duplicate, I would imagine it would be valuable to someone who doesn't know what the operator is called and is trying to search for an answer by describing the syntax, which is what I was trying to do. – Amr Bekhit May 15 '13 at 11:48
  • more specifically expressions separated by comma operators are evaluated from **left to right**.The result of such comma expression is the value of **rightmost** expression – Anirudha May 15 '13 at 12:07
  • @AmrBekhit Nobody blames you for not finding the duplicate right-away, it nevertheless is one though. The question will still remain in existence for possible future users, just now with links to even more information. – Christian Rau May 15 '13 at 12:17

6 Answers6

37

This is the comma operator: evaluation of a, b first causes a to be evaluated, then b, and the result is that of b.

int a = (1, 2, 3); first evaluates 1, then 2, finally 3, and uses that last 3 to initialise a. It is useless here, but it can be useful when the left operand of , has side effects (usually: when it's a function call).

  • Typically I write it like `({ doSomething(); x; })`, which is especially handy for macro definitions which work with temporary results. Is there any difference between these notations, besides the fact that I use semicolon rather than comma to separate these (sub-)expressions? – leemes May 15 '13 at 11:07
  • 2
    @leemes That is invalid in standard C and in C++, but it is accepted by some compilers (GCC at least) as an extension to allow statements to be used, not merely expressions, so that you could do `({ if (0) { 1; } 2; })`. –  May 15 '13 at 11:08
  • "usually: when it's a function call" can you explain please? i'm asking because i'm confused about the context. do you mean foo(T,T2),this comma or foo(T),foo(T)? – Koushik Shetty May 15 '13 at 11:09
  • @hvd Thanks for clarifying. Oh my gosh, I didn't know I wrote non-standard code in the past few years! – leemes May 15 '13 at 11:09
  • In particular, it's useful in places like a `while` condition, where you're only allowed a single expression. Otherwise, you might just as well write two statements when you want to do two things. – Mike Seymour May 15 '13 at 11:10
  • Can you add a reference to the "comma operator" page on wikipedia? I think the answer will be more complete and I can mark it as accepted. – Amr Bekhit May 15 '13 at 11:12
  • @Koushik The latter, my example would be more of `int a = (f(), b);` –  May 15 '13 at 11:12
  • @AmrBekhit If I have to link to an external source in an answer, I would prefer something more authoritative than Wikipedia :) I'll see if I can find something. (Edit: actually, Krishnabhadra has already put up a good answer with a reference that you might accept.) –  May 15 '13 at 11:16
  • 1
    What about [this?](http://en.cppreference.com/w/cpp/language/operator_other#Built-in_comma_operator) – leemes May 15 '13 at 11:18
  • @hvd Unfortunately there's no HTML web-version of the standard. Until that day, *cppreference* might be regarded as canonical as a link can get, I think. – Christian Rau May 15 '13 at 11:20
  • @MikeSeymour: Hehe... I was going to name Subbotin's carryless rangecoder as the probably most infamous example of that kind of thing (I'm inclined to name it "abuse"). It contains several loops like `while((low^low+range) – Damon May 15 '13 at 12:00
  • 1
    more specifically expressions separated by comma operators are evaluated from **left to right**.The result of such comma expression is the value of **rightmost** expression – Anirudha May 15 '13 at 12:08
19

It uses the comma operator, which just evaluates each operand expression sequentially (introducing proper sequence points in between) and returns the last one. Thus your example is actually equivalent to int a = 3;.

But it is indeed one of the least used operators in C and C++ and not to be confused with the commas used in function call expressions, initializer lists, and all the other places. A not so rare use-case would be multiple increments in for loops (for(...; ...; ++i,++j)), even though you probably never thought about this actually using a so-called comma operator.

Another interresting use case is when trying to put multiple conceptually related expressions into a single statement (like a return) for the sake of clarity and conciseness, like in an implementation of the good old frexp with its weird pointer return argument (ignore the fact that proper C++ would just return a pair):

double frexp(double arg, int *exp)
{
    if(...)
        return *exp=..., result;
    ...
}

which is much more streamlined than the equivalent

double frexp(double arg, int *exp)
{
    if(...)
    {
        *exp = ...;
        return result;
    }
    ...
}
Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • 4
    I like this answer better than the currently top-voted one by hvd, actually, but who am I to argue with the Internet? `:)` – user May 15 '13 at 11:22
  • 1
    @ChristianRau remember [this](http://stackoverflow.com/questions/16538458/how-to-make-i-x-works-as-i/16538741#16538741), you could do that using comma here and show the example:-) – Koushik Shetty May 15 '13 at 11:30
  • @Koushik Hah, right! Still weird, but better than the `?:` version. Still I won't show it in this answer, since it isn't really a reasonable use case, I think. But +1 for an interresting cross-reference. – Christian Rau May 15 '13 at 11:32
  • yes way better than `?:` and yes your answer is complete as it is. – Koushik Shetty May 15 '13 at 11:34
7

Wiki: Comma operator

i = (a, b, c);          // stores c into i
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
nurettin
  • 11,090
  • 5
  • 65
  • 85
5

It is comma operator. C11 standard tells about one use case of this kind of operator.

C11 standard 6:5:17

Comma operator

The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)

The comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call f(a, (t=3, t+2), c) the function has three arguments, the second of which has the value 5.

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
3

It just evaluates 1, 2 and 3 (since they are only values, but could as well be functions calls), and sets the value (or return value) of the last one to the left operand (in your example, a).

Maybe this will help you understand how it works:

#include <stdio.h>

int toto()
{
  printf("toto()\n");
  return (21);
}

int tata()
{
  printf("tata()\n");
  return (42);
}

int main()
{
  int a = (toto(), tata());
  printf("%d\n", a);
  return (0);
}

Output:

toto()
tata()
42

Edit: Tha's C code, works the same in C++

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
yoones
  • 2,394
  • 1
  • 16
  • 20
3

This is the comma operator. It "wraps" multiple expressions, evaluates them from left to right, and the value of the whole expression is determined by the last sub-expression. In your example, it evaluates to 3.

A situation where the comma operator is especially handy is if you want to do multiple things in a for-loop "increment" expression, for example to increment two variables.

Example: Iterate an image along the diagonal, using x and y as separate variables. I use two separate variables for x and y because I might want to change one of them in the loop independently from the other (remember, it's just a stupid example). So I want to increment both x and y in the "increment" statement of the for-loop:

for(int x = 0, y = 0; x < width && y < height; ++x, ++y) {
    // ...                                     ^^^^^^^^
}

Note that the "initialization" expression of the for-loop does not use the comma operator; it just declares two variables.

leemes
  • 44,967
  • 21
  • 135
  • 183
  • 1
    I'd rather change *"separator"* to *"operator"* in the first sentence, since the former would rather be what I call the usual (non-operator) use of commas. But good that you pointed out the difference to the initialization expression of the for-loop. – Christian Rau May 15 '13 at 11:18
  • Oops, this was by accident anyway. Thanks for pointing it out ;) – leemes May 15 '13 at 11:19