views:

1449

answers:

13

Hello, I have been programming in C and C++ for a few years and now I'm just now taking a college course in it and our book had a function like this for an example

int foo(){
  int x=0;
  int y=20;
  return x,y; //y is always returned
}

I have never seen such syntax. In fact, I have never seen the , operator used outside of parameter lists. If y is always returned though, then what is the point? Is there a case where a return statement would need to be created like this?

(Also, I tagged C as well because it applies to both, though my book specifically is C++)

+3  A: 

This is the comma operator (,).

Both expressions x and y are evaluated. The result of the overall expression is y, i.e., the latter value.

It's hard to say why it is used here. I guess, for demonstration purposes. Clearly the function could be refactored to:

int foo()
{
  return 20;
}
Daniel Daranas
@mmyers: and the answer given here is... there doesn't appear to be any point.
Jefromi
@Jefromi: That wasn't there when I commented.
Michael Myers
+20  A: 

The comma in parameter lists is just there to separate the parameters, and is not the same as the comma operator. The comma operator, as in your example, evaluates both x and y, and then throws away x.

In this case, I would guess that it is a mistake by someone who tries to return two values, and didn't know how to do it.

Thomas Padron-McCarthy
+20  A: 

According to the C FAQ:

Precisely stated, the meaning of the comma operator in the general expression

e1 , e2

is "evaluate the subexpression e1, then evaluate e2; the value of the expression is the value of e2." Therefore, e1 had better involve an assignment or an increment ++ or decrement -- or function call or some other kind of side effect, because otherwise it would calculate a value which would be discarded.

So I agree with you, there is no point other than to illustrate that this is valid syntax, if that.

If you wanted to return both values in C you would need to create a struct containing x and y members, and return the struct instead:

struct point {int x; int y;}

Of course, the ability to return multiple values directly is wonderful in languages such as Python that support it.

Justin Ethier
Thank you for explaining the operator.
Jeff Davis
Your `point` struct needs a constructor taking two `int` parameters.
Mark Ransom
+24  A: 

The comma operator is primarily used in for statements like so:

for( int i=0, j=10; i<10; i++, j++ )
{
    a[i] = b[j];
}

The first comma is not a comma operator, it's part of the declaration syntax. The second is a comma operator.

Joel
I don't think this really answers the OP's question...
Chris Cooper
+3  A: 

That looks like a terrible example of code. It might be valid syntax in C/C++, but I can't think of a reason why you'd ever want to do that.

If you want to return both x and y, a better way to do it in C++ would be to define a "Point" class or struct with x and y properties, and return that. Another option would be to pass in x and y by reference, then set the values appropriately in the method.

If the method is going to just return y, I would just "return y;". If x needs to be "evaluated" before the return statement, it should be done on a separate line.

Andy White
+5  A: 

Much like everyone commenting here thinks it is pointless and I don't disagree, just looking at the example, I'm going to make a guess that's not much better:

The writer was getting a compiler warning about x not being used within the function, and this was an easy way to get the warning to go away.

Joel Rondeau
I just tried this with g++, and there is a warning if you use -Wall. I'm not sure whether to praise the author for compiling code before putting it in the book or condemn the author for coming up with this solution. Although, it might have been interesting if the author had actually used this as an opportunity to talk about compiler warnings and such.
clahey
I take it back. I just tried the code as given and that still gives a warning. Maybe he's on a different compiler.
clahey
He also has a book on Java(a red flag right there) so probably using MVC++
Earlz
Seemed VS6.0 would be the likely candidate and it does give a warning C4189 : local variable is initialized but not referenced if the "x," is removed, provided warnings are set to level 4 (highest).
Joel Rondeau
If that was the author's intent, it was a bad idea... writing code that looks like it returns two values when it fact it only returns one is going to do more harm than good.
Jeremy Friesner
+5  A: 
 struct Point {
   int x, y;
   Point(int x_) : x(x_), y(0) {}
   Point(const Point& p) : x(p.x), y(p.y) {}
   Point operator, (int y_) const { Point p=*this; p.y = y_; return p; }
 };

 Point get_the_point () {
    int x = 0;
    int y = 20;
    return (Point)x, y;
 }

:p

KennyTM
That's so not C++. I mean, it'll compile, but that's so unreadable. Ick.
clahey
@clahey: Then you will hate this: http://www.boost.org/doc/libs/1_42_0/libs/assign/doc/index.html
KennyTM
I think the boost stuff is definitely questionable, but there's something worse about what you have there. For example: "return (Point)1, 2, 3;" returns (1,3). "return (Point)1" returns (1,0). Neither of those feels like intuitive behavior.Also, your notation doesn't save anything. If you just declare a proper constructor that takes two ints, you can just write "return Point(x, y);" It doesn't save even a single character of typing and is more readable. The boost stuff at least saves a lot of typing.
clahey
@clahey: Note that I'm not advocating this style (see the ":p"?), I'm just showing there maybe a "point" that a comma operator is abused (I can't place a multi-line comment).
KennyTM
That is so wonderfully *evil*. Is there an equivalent of the IOCCC for C++?
John Bode
+1  A: 

On the one hand, it could be an honest mistake on the part of the writer.

On the other hand, the writer might be explaining syntactically correct correct code, versus compiler warnings.

Either way, the only way to return multiple results would be to define a class and use its instance, or perhaps an array or collection.

Olaseni
+6  A: 

This doesn't really answer the original question at all but might be of interest to some people, but if you wanted to it to return both in C++ you'd need to write it like this (and would need a c++0x compiler)

tuple<int, int> foo()
{
    int x = 0;
    int y = 20;
    return make_tuple(x, y);
}

The access it like this -

tuple<int, int> data = foo();
int a = get<0>(data);
int b = get<1>(data);
John Burton
+1, was about to post this :-)
missingfaktor
Personally, I'd prefer: int a = 0, b = 0; tie(a,b) = foo();
Noah Roberts
I didn't know about tie, I'll have to try that out.
John Burton
In a C++03 compiler, just return a `pair`. This doesn't directly generalize to more than two values, of course.
David Thornley
+2  A: 

There is no point in that return statement.

If x were declared volatile, it would force an access (since at least in C++ references to volatile variables are considered to be externally observable behavior), but it isn't.

If, instead of x, there was some sort of calculation with side effects, it would do that calculation and then return y. However, a non-volatile x has no side effects. The implementation is not required to execute any code that has no side effects or externally observable behavior. The comma operator executes whatever is on the left side of the comma, disregards the result, and executes and keeps the value of the right side (except that it's free to ignore the left side of the operator in this case).

Therefore, the return x, y; statement is the exact same thing as return y;. If x wasn't just a completely meaningless thing to execute, it would be stylistically better to write it as x; return y;, which is the precise same thing. It wouldn't be nearly as confusing that way.

David Thornley
+1  A: 

This is the comma operator. Such syntax can be used to disable warning from compiler about unused variable x.

osgx
+1  A: 

Outside of for loops the other major user of this comman operator (as apposed to the function call version) is in macros that return a value after doing some stuff. These are other ways to do this now, but I think that the comman operator used to be the cleanest way.

#define next(A, x, y, M) ((x) = (++(y))%(M) , A[(x)])

Please note that this macro is a bad example of macros in general because it repeats x and probably for other reasons. Use of the comma operator in this fashion should be rare. The example from your book was probably an attempt to make a code exampe fit within the number of lines available for that example.

nategoose
A: 

Is there a case where a return statement would need to be created like this?

IMO, I would never use multiple returns in a function like the book example. It violates structured design. Nevertheless, there are many programmers that do! Debugging someone else's code I have assigned a value to a global variable in each return statement so I could figure out which return executed.

d hughes