1

Simply stated, why does the following code compile?

#include<iostream>

int foo(){
    return 0,1;
}

int main(){
    int a,b = foo();
    std::cout << a << " " << b << std::endl;
    std::cout << foo();
    return 0;
}

I am using a 64-bit Window's machine, and compiling with Dev-C++ (using the MinGW GCC 4.5.2 32-bit compiler).

This code prints the following output:

2686824 1
1

I strongly suspect that the value contained in a is the usual garbage stored in uninitialized variables.

It is clear from this question that returning multiple values from functions is not common practice in industry, and it is definitely discouraged and penalized in programming courses taught at academic institutions.

So why does it work? As I've matured as a programmer, I've realized the incredible value of compiler errors, which are infinitely more intelligible than linker or run-time errors, and obviously way better than bugs.

To be clear, I'm more interested in why this has been allowed from a language design perspective, rather than the technical specifics of how the compiler does its thing (unless, in this case, implementation realities or technical consequences have made it difficult/impossible to detect/manage multiple return variables).

Are there some esoteric cases where multi-variable return statments were deemed useful?

Community
  • 1
  • 1
NauticalMile
  • 1,625
  • 3
  • 16
  • 29
  • 1
    This is the same as `int a; int b = foo();` You should get a warning for uninitialized `a` if you have your compiler set up to be appropriately whiny. – tadman Apr 06 '15 at 19:59
  • Yeah, the example just highlights the fact that c++ does not assign the multiple return variables to multiple variables in the calling code. – NauticalMile Apr 06 '15 at 20:00
  • Did you notice that the question link you have, *none* of the answers look like the code you have posted here? – crashmstr Apr 06 '15 at 20:03
  • 3
    Comma is an operator in C. The expression `2,3,4` is just `4`. – Lee Daniel Crocker Apr 06 '15 at 20:04
  • @crashmstr They all just said 'I don't use multiple return statements.' Unless I missed something, none of them mentioned the comma operator. – NauticalMile Apr 06 '15 at 20:06
  • @NauticalMile Almost all of them show or mention possible ways of returning multiple values: reference parameters, returning a `std::pair`, returning `std::tuple`, or returning a `class` or `struct`. *If* the comma operator did this, then I would expect that some answer would mention it. – crashmstr Apr 07 '15 at 12:02

2 Answers2

16

You still only return one value, which is 1.

return 0,1;

makes use of the comma operator, its result is its right hand side. With the right warning level, your compiler (gcc and clang at least) will warn because its left hand side has no effect.

If you actually want to return multiple values, you can return a std::tuple (or std::pair):

auto fun () {
    return std::make_tuple(0,1);
}

int main () {
    int a, b;
    std::tie(a,b) = fun();
    // Now a == 0, b == 1
}

Equivalent alternative as of C++17:

auto fun () {
    return std::make_tuple(0,1);
}

int main () {
    auto [a,b] = fun();
}

Live

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
4

0,1 is an operator that does nothing except evaluate both expressions in order and results in the value of the second operator (1). So return 0,1 is equivalent to saying return 1.

int a,b = foo(); creates two variables. a is uninitialized, and b is assigned the return value of foo().

That's why the value of b is 1 and the value of a is wacky (it's undefined).


IME, the main benefit of the comma operator is for loops in C. For example, suppose you wanted to enumerate elements of a linked list. Lists don't have a built-in concept of order so you end up keeping two trackers of position in the list.

for (index = 0, curr_node = list_begin; 
  curr_node != NULL; 
  ++index, curr_node = curr_node->next)
{
  // Stuff
}

It's a convenient little trick for readability and it also guarantees that index/curr_node are in sync no matter what you do with break or continue.

QuestionC
  • 10,006
  • 4
  • 26
  • 44
  • first part in for is just multiple initialization, not comma operator. – vsoftco Apr 06 '15 at 20:20
  • You weren't able to initialize variables in the first part of the `for` trinary until C++. I assume they added it for C99 as well. "Back in my day" you had to stick a single expression in there, so the comma was needed to perform double-assignments. – QuestionC Apr 06 '15 at 22:03
  • AFAIK, there's no way to perform a double-initialization. – QuestionC Apr 06 '15 at 22:14
  • 1
    Ohh I see, thanks for the clarification. I would just not use a double initialization there though, as it creates confusion to people that don't really know what the comma operator is. Your answer is perfectly fine though, didn't downvoted :) – vsoftco Apr 06 '15 at 22:17