views:

370

answers:

9

Having been writing Java code for many years, I was amazed when I saw this C++ statement:

int a,b;
int c = (a=1, b=a+2, b*3);

My question is: Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)

I think the compiler will see it the same as the following:

int a=1, b=a+2;
int c = b*3;

(What's the offical name for this? I assume it's a standard C/C++ syntax.)

+15  A: 

It's the comma operator, used twice. You are correct about the result, and I don't see much point in using it that way.

Matthew Flaschen
+9  A: 

Looks like an obscure use of a , (comma) operator.

It's not a representative way of doing things in C++.

Maciej Hehl
+3  A: 

Dunno its name, but it seems to be missing from the Job Security Coding Guidelines!

Seriously: C++ allows you to a do a lot of things in many contexts, even when they are not necessarily sound. With great power comes great responsibility...

Pontus Gagge
It's actually well-defined. The comma operator is a sequence point.
Matthew Flaschen
@Mathew Flaschen: It may be well defined does not mean it is good practice.
Martin York
+1  A: 

Its strictly coding style and won't make any difference in your program. Especially since any decent C++ compiler will optimize it to

int a=1; 
int b=3;
int c=9;

The math won't even be performed during assignment at runtime. (and some of the variables may even be eliminated entirely).

As to choice of coding style, I prefer the second example. Most of the time, less nesting is better, and you won't need the extra parenthesis. Since the use of commas exhibited will be known to virtually all C++ programmers, you have some choice of style. Otherwise, I would say put each assignment on its own line.

CrazyJugglerDrummer
Actually it's not the comma operator when used in `int a=1, b=2`. As far as the syntax is concerned, it's a different comma.
Steve Jessop
Thanks, wasn't sure if about the specifics. updated :D
CrazyJugglerDrummer
+2  A: 

This is called 'obfuscated C'. It is legal, but intended to confuse the reader. And it seems to have worked. Unless you're trying to be obscure it's best avoided.

Hotei

Hotei
I don't consider this obfuscated.
Matthew Flaschen
@Mathew Flaschen: You are then officially in the minority then.
Martin York
I'm not sure that I'd call it obfuscated, since that would imply that the whole purpose was to hide what's happening, and it's too straightforward for that. However, the comma operator in this case adds nothing of value to the program and is likely just to confuse other programmers - albeit briefly if they're properly familiar with the comma operator. So, confusing yes, obfuscated, no.
Jonathan M Davis
@Jonathan M Davis: Webster.. obfuscate, intransitive verb: to be evasive, unclear, or confusing. Hence, Hotei and Martin are correct in their judgment as this being 'obfuscated C'.
GrafikRobot
Well, dictionary aside, generally when people talk about obfuscated C, they're talking about when people write code which is specifically supposed to be really confusing and hard to decipher. There was purpose behind it. And while the comma operator may aid in that, in this case, it is not obfuscated in that sense. So, according to common usage, I'd definitely say that it isn't obfuscated. However, I suppose that per the dictionary definition, confusing and obfuscated are pretty much the same thing. In either case, it's generally best not to use the comma operator outside of for loops.
Jonathan M Davis
Looking at how many people thought this is an example of the "comma" operator I stand by my statement that 1) it's obfuscated 2) it worked.Hotei
Hotei
+7  A: 

The only "good-style" use for the comma operator might be in a for statement that has multiple loop variables, used something like this:

// Copy from source buffer to destination buffer until we see a zero
for (char *src = source, *dst = dest; *src != 0; ++src, ++dst) {
    *dst = *src;
}

I put "good-style" in scare quotes because there is almost always a better way than to use the comma operator.

Another context where I've seen this used is with the ternary operator, when you want to have multiple side effects, e.g.,

bool didStuff = DoWeNeedToDoStuff() ? (Foo(), Bar(), Baz(), true) : false;

Again, there are better ways to express this kind of thing. These idioms are holdovers from the days when we could only see 24 lines of text on our monitors, and squeezing a lot of stuff into each line had some practical importance.

Kristopher Johnson
Barely, in cases with multiple vars changing, I'd start thinking small function and not be forced to worry about , and scope.
Michael Dorgan
I agree that these examples are not good ones. But they do at least serve as examples where the writer would have a reason to use the comma operator, unlike the questioner's example where it is used for no reason at all.
Kristopher Johnson
Your copy is backwards, and that's a declaration of two `char *`, not a use of the comma operator.
Matthew Flaschen
Fixed ordering. And true, the declarations are not an example of the comma operator, but the `++src, ++dst` clause is.
Kristopher Johnson
You're right. I missed that part.
Matthew Flaschen
+2  A: 

Your sample code use two not very well known by beginners (but not really hidden either) features of C expressions:

  • the comma operator : a normal binary operator whose role is to return the last of it's two operands. If operands are expression they are evaluated from left to right.
  • assignment as an operator that returns a value. C assignment is not a statement as in other languages, and returns the value that has been assigned.

Most use cases of both these feature involve some form of obfuscation. But there is some legitimate ones. The point is that you can use them anywhere you can provide an expression : inside an if or a while conditional, in a for loop iteration block, in function call parameters (is using coma you must use parenthesis to avoid confusing with actual function parameters), in macro parameter, etc.

The most usual use of comma is probably in loop control, when you want to change two variables at once, or store some value before performing loop test, or loop iteration.

For example a reverse function can be written as below, thanks to comma operator:

void reverse(int * d, int len){
    int i, j;

    for (i = 0, j = len - 1 ; i < j ; i++, j--){
       SWAP(d[i], d[j]);
    }
}

Another legitimate (not obfuscated, really) use of coma operator I have in mind is a DEBUG macro I found in some project defined as:

#ifdef defined(DEBUGMODE)
#define DEBUG(x) printf x
#else
#define DEBUG(x) x
#endif

You use it like:

DEBUG(("my debug message with some value=%d\n", d));

If DEBUGMODE is on then you'll get a printf, if not the wrapper function will not be called but the expression between parenthesis is still valid C. The point is that any side effect of printing code will apply both in release code and debug code, like those introduced by:

DEBUG(("my debug message with some value=%d\n", d++));

With the above macro d will always be incremented regardless of debug or release mode.

There is probably some other rare cases where comma and assignment values are useful and code is easier to write when you use them.

I agree that assignment operator is a great source of errors because it can easily be confused with == in a conditional.

I agree that as comma is also used with a different meaning in other contexts (function calls, initialisation lists, declaration lists) it was not a very good choice for an operator. But basically it's not worse than using < and > for template parameters in C++ and it exists in C from much older days.

kriss
In deed, java support the similar syntax in loop: for(int i=0,j=len-1; i<j; i++,j--){...} However, java totally disallow other uses of comma operator (except defined variables): b = (a=1, a+2); // cause error
joejax
Whoah, surely the else clause should just throw away x? Then no side effects.
JBRWilkinson
@JBRWilson: I think the point is that if the second thing inside the parenthesis (e.g. d++) has a side effect, the side effect still happens whether or not DEBUGMODE is defined. It's still pretty ugly.
JeremyP
Sorry JBRWilkinson, not JBRWilson.
JeremyP
A: 
Norman Ramsey
+1  A: 

Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)

It's both a choice of coding style and it has a real benefit.

It's clearly a different coding style as compared to your equivalent example.

The benefit is that I already know I would never want to employ the person who wrote it, not as a programmer anyway.

A use case: Bob comes to me with a piece of code containing that line. I have him transferred to marketing.

JeremyP