26 comments

[ 3.1 ms ] story [ 65.6 ms ] thread
It's also occasionally useful in the construction of #define macros, where readability is often sacrificed for proper semantics regarding side effects and part-of-speech.
C++ allows overloading the comma operator. This can be (ab)used to make the following syntax work for, e.g., initializing a vectorish type:

    MyType obj = 1, 2, 3;
Due to the precedence of operators, this is actually equivalent to

    ((MyType obj = 1), 2), 3;
so as long as the overloaded assignment operator returns an object that the comma operator mutates and returns, this can be made the have effect of initializing the declared object to a "list".

This trick is used by Boost Spirit to allow things like (example from http://stackoverflow.com/questions/54142/c-comma-operator)

    keywords = "and", "or", "not", "xor";
I think that when you overload the comma operator in C++, you change the nature of the sequence point. I believe you're no longer guaranteed to have "1, 2, 3" evaluated in that order. In your example, this doesn't matter, but if it was "f1(), f2(), f3()" and for some reason the sequence of those calls determined what each returned, you might have a problem. I could be wrong here though--my C++ is rusty from years of disuse.
Item #7 in More Effective C++ is to "never overload &&, || or ," because it changes the order of evaluation (with the boolean logic operators, it changes because the usual short-circuiting behavior is gone since the second argument has to be evaluated to pass it as an argument).
Cute way to reverse a string, taken from the K+R:

    for (i = 0, j = strlen(s)-1; i < j; i++, j--) 
           c = s[i], s[i] = s[j], s[j] = c;
also one the lesser used operator in javascript too.
Comma is quite useful for compacting cleanup code in abnormal function exits. E.g. from this:

  if (...)
  {
    cleanup();
    return -2;
  }
to this

  if (...)
    return cleanup(), -2;
Linux kernel uses this pattern in several places. However the best comma use is, of course, for messing your enemies' code:

  foo,();
Could even be used with lvalues

   (++k, ++k, k) += 100;
(works with gcc 3.4)
Is the behaviour defined in this case? If so, what does it do?
Because the comma adds a sequence point, it should be defined: the post-increments both happen before the use of the k lval.
This is probably one of the better use cases for the comma operator in C.

http://stackoverflow.com/questions/52550/what-does-the-opera...

  string s;
  while(read_string(s), s.len() > 5)
  {
   //do something
  }
versus

  string s;
  read_string(s);
  while(s.len() > 5)
  {
   //do something
   read_string(s);
  }

    for (read_string(s); s.len() > 5; read_string())
or just fix the damned read_string function to return the length read. [nevermind s.len() is unlikely to appear in C.]
(comment deleted)
So is class string, so we're really talking about uses for the operator in C/C++.

I'd say the for version is better if you can declare the variable in the initialization section (tighter scope), but the while version has you repeat yourself less if the variable's already there.

I find this easier to read:

  string s;
  for (;;)
  {
    read_string(s);
    if (s.len() <= 5)
      break;
    //do something
  }
(comment deleted)
The comma operator is pretty useful in macros:

    #define something(...) (printf(... some debug message ...),real_something_expression)
    foo = something(...)
This way you can create macros returning values and printing debug messages at the same time.
This is what I was going to post, comma operator is really useful in macro for example when overriding mutex lock/unlock to call printf before and still keep the returned value and not change all calls.
The problem with having read_string return the length is that you have to write

  while (read_string(s) > 5) // loop until the string length is greater than 5
because it's not intuitive that read_string will return the length of the string. You don't save anything this way.
Have read_str return const char *

while (strlen(read_string(s)) > 5)

I find the comma useful in deletion scenarios. For example, rather than just "free(x)" or "delete x" (after which the variable is undefined and can't be used anyway), I like to use the comma to add a NULL assignment. So, "free(x), x = NULL". It doesn't really need to be that way, but it's nice for avoiding random behavior in case the variable is referenced later; and the chain on one line makes it unlikely that the 2nd part will be forgotten.
why don't you use the semicolon? the comma is only adding something more if you're using the final value.
It would hardly ever matter, that's true. But I can certainly contrive something that would require it, such as:

    if (something) f();
    else delete x, x = NULL;
Of course, I don't personally use "else" without a block, so it's just an example; I'm not suggesting it's a good idea.
In Perl:

  my ($a) = (8,9) || (20,21);
  print "\$a = $a\n";
Gives:

  $a = 9
Due to the comma operator.
The comma in the for loop is quite common, it is actually on the Indian Hill coding style and standard.
For those who want to see a serious use of this operator, see http://code.google.com/p/cii/source/browse/trunk/include/exc... line 35. This from an exception (try, catch, except macros) library for the C language. It is from a book called "C interfaces and implementations", probably one of the best books on good C programming I have ever (and still) read.

It's special in the fact that it's written by Hanson (who also co-wrote the LCC compiler, you might have seen ID Software use this compiler) and the book uses Knuth's Literary Programming technique for the source code in the book ;)