Multiple return in C/C++

Asked

Viewed 12,732 times

9

Is it possible to return multiple values? For example:

umafuncao()
{
    int x = 1, y = 2;
    return x,y;
}

void main()
{
    int a, b;
    a, b = umafuncao();
}

I’m asking this question because I built a code using this structure for a task and passed all the tests, but I can’t find anything saying that this is functional.

Follows the code:

int findMaxCrossingSubArray(TItem *Receita, int low, int mid, int high)
{
    int i, j, maxLeft, leftSum = -100000, maxRight, rightSum = -1000000;
    int sum = 0;
    for( i = mid; i >= low; i--)
    {
        sum = sum + Receita[i].Chave;
        if( sum > leftSum)
        {
            leftSum = sum;
            maxLeft = i;
        }
    }
    sum = 0;
    for(j = mid + 1; j <= high; j ++)
    {
        sum = sum + Receita[j].Chave;
        if(sum > rightSum)
        {
            rightSum = sum;
            maxRight = j;
        }
    }
return (maxLeft, maxRight, leftSum + rightSum);
}

int findMaxSubArray(TItem *Receita, int low, int high)
{
int mid;
int leftLow, leftHigh, leftSum;
int rightLow, rightHigh, rightSum;
int crossLow, crossHigh, crossSum;

if(high == low)
{
    return (low, high, Receita[low].Chave);
}
else
{
    mid = (low + high)/2;
    leftLow, leftHigh, leftSum = findMaxSubArray(Receita, low, mid);
    rightLow, rightHigh, rightSum = findMaxSubArray(Receita, mid+1, high);
    crossLow, crossHigh, crossSum = findMaxCrossingSubArray(Receita, low, mid, high);
    if((leftSum >= rightSum) && (leftSum >= crossSum))
        return (leftLow, leftHigh, leftSum);
    else if((rightSum >= leftSum) && (rightSum >= crossSum))
        return (rightLow, rightHigh, rightSum);
    else
        return (crossLow, crossHigh, crossSum);
    }
}

int main()
{
    TItem *Receita;
    int low = 0, ndias, *taxa, lucro;
    taxa = malloc(sizeof(int));

    ndias = Carrega(&Receita, taxa);

    //Aqui começa a lógica para calculo do lucro maximo:

    low, ndias, lucro = findMaxSubArray(Receita, low, ndias-1);
    printf("%d", lucro > 0 ? lucro : 0);
    Libera(&Receita);
    return 0;
}
  • To return more than one value, you must return an array or a Pointer.

  • Does the first part have any relation to the second part? Explain better why the second part is important. You are talking about this return (low, high, Receita[low].Chave)?

  • If you create a struct (composite data type) you can use it to package multiple values in function return.

  • Take a look at [tour]. You can accept an answer if it solved your problem. You can vote on every post on the site as well. Did any help you more? You need something to be improved?

4 answers

9

Multiple return

Neither C nor C++ allow returning various values in the function.

The most common when it is necessary to return more than one value would be to pass one parameter for reference, so you put a value on it inside the function and when you exit it this value will be in the passed variable. This is usually used when the returned values have little relation or are using older techniques.

Another more modern possibility is to use a data structure that encapsulates all values. It may be some kind of collection, such as array standard of C, the Vector which obviously only work if the type is the same, but they don’t give good semantics to the code. It can be a struct or class, or a Tuple, the most common in such cases.

The tuple is advantageous when the data is related and heterogeneous, as in a class. Returning a class is used when this data has a larger semantics in the application and is probably used elsewhere. It is not worth creating a class just for this single multiple return.

Comma operator

But what you saw in the code presented is not a multiple return. The operator represented by the comma is the sequence operator. It will execute all expressions separated by each comma in order and the last expression will be responsible for the result of the entire sequence. Then in:

return (maxLeft, maxRight, leftSum + rightSum);

the return will be the value of leftSum + rightSum. Don’t ask me why it has the previous values. They will be discarded and have no function there. In this case, it makes no sense because they do not perform anything, they only take the value that will be later discarded.

7

What you’re wearing without realizing it’s the dark Comma Operator. This operator evaluates the expression on the left, discards its value, evaluates the one on the right, and returns its value. For example: 1, 2 has the value 2. So, int x = 1, 2; is equivalent to int x = 2; . This seems pointless, but if you have an expression like int x = a(), b(); and the function a have side effects (modify program status), will be different from int x = b();

In case you use the comma operator as lvalue (left side of an assignment), as in a, b = umafuncao();the compiler is only allowing because you are using C++, which allows this (therefore, your C tag is inappropriate to this question).

Now as for your solution, I do not recommend using an array to return its values, as suggested, because its values, despite having the same type of data, have semantics different. This is relevant because whoever receives your return will have to look at your code to find out what each position of your vector means. The most appropriate is to create a simple class that maintains the values you want to return by giving them the proper names (leftLow, leftHigh etc.). Contrary to what may seem, no, such a class is not heavy as it is quite optimized-- it is saved practically as a sequence of the bits of its members.

  • 1

    +1 for the explanation of the comma operator. Two comments only: int x = 1.2; is not a valid expression. This expression should return something like "expected unqualified-id before Numeric Constant" Já, int a = 1; int b = 2; int x = a, b; is valid but at the end x will be 1;

  • You’re right. Parentheses are missing. I’ll fix. :)

4

Hello you can make use of vectors for this.

Example

int * umafuncao()
{
    static int retorno[2];
    retorno[0] = 1;
    retorno[1] = 2;

    return retorno;
}

void main()
{
    int *callfunc;
    int a, b;
    callfunc = umafuncao();
    a = callfunc[0];
    b = callfunc[1];
}

Or make use of pointers...

void umafuncao(int *a, int *b)
{
    //Altero o valor direto na posição da memoria da variavel.
    *a = 1;
    *b = 2;
}

void main()
{
    int a, b;
    umafuncao(&a, &b);
}
  • 3

    I think it’s kind of fragile to use static memory to return values like in the first example. I think it would be more normal to simply return a struct.

  • Yes Hugo, I’m not very expert on C manjo over PHP/JAVA.. I just suggested how I would, I don’t know if it’s the right way. I just wanted to help..

2

C++17 introduced us to the wonderful world of Structured Links (Structured Bindings).

This new Feature allows you to return a tuple (or an object that behaves like one), and use a small syntactic sugar to fill multiple variables with the items of this object:

#include <iostream>
#include <tuple>

auto f() {
    return std::make_tuple(1, 2);
}

int main() {
    auto [a, b] = f(); // Aqui
    std::cout << '(' << a << ',' << b << ')';
}

See in coliru

This code snippet is equivalent to the following snippet, compileable in C++11:

#include <iostream>
#include <tuple>

std::tuple<int, int> f() {
    return std::make_tuple(1, 2);
}

int main() {
    int a, b;
    std::tie(a, b) = f();
    std::cout << '(' << a << ',' << b << ')';
}

See in coliru

Browser other questions tagged

You are not signed in. Login or sign up in order to post.