2011-07-16 2 views
15

Можно создать дубликат:
returning multiple values from a functionКак вернуть два значения из функции?

Пусть я passsed два значения функции iCalculate(int x, int y) и это iCalculate возвращает два значения. Это выглядит следующим образом: -

  • (х * у)
  • (х/у)

Теперь, как я должен вернуть вышеуказанные два значения одновременно с одной и той же функции?

Мой подход был: -

int* iCalculate(int x,int y){ 
    int temp[2]; 
    temp[0] = x*y; 
    temp[1] = x/y; 
    return temp; 
} 
+0

Что ваш вопрос ?? –

ответ

28

возвращая адрес первого элемента локального массива имеет неопределенное поведение (по крайней мере разыменования его более поздняя версия).

Вы можете использовать выходные параметры, то есть, передать два указателя, и установите значения внутри

void Calculate(int x, int y, int* prod, int* quot) 
{ 
    *prod = x*y; 
    *quot = x/y; 
} 

использование:

int x = 10,y = 2, prod, quot; 
Calculate(x, y, &prod, &quot) 

Другая вещь, которую вы можете сделать, это упаковать ваши данные в структуры

typedef struct 
{ 
    int prod; 
    int quot; 
} product_and_quot; 


product_and_quot Calculate(int x, int y) 
{ 
    product_and_quot p = {x*y, x/y}; 
    return p; 
} 
+2

+1 5 секунд быстрее ... – eckes

+12

Но не быстрее меня для опции 'struct' return. Что с программистами C, что они всегда думают о решении указателя, а второе - второе? ;) –

+0

Поскольку возврат/передача struct означает копирование всех элементов структуры. Вот почему я предлагаю третье решение: возвращать/передавать указатель на структуру :-) – dragon135

11

Это не сработает, так как вы возвращаете указатель на временный массив, который wil l прекратить существование при возврате функции.

Вместо определения

typedef struct { int first, second; } IntPair; 

и возвращает объект этого типа.

(Это то, что стандартные функции библиотеки div и ldiv делать, за исключением того, что они называют тип по-разному.)

+0

Есть ли какая-либо функция, состоящая из более чем одного типа возврата? – Abhineet

+3

'div' и' ldiv', прежде всего.Большинство других возвращаются указателем, хотя на современных машинах это не очень важно (это была оптимизация). –

2

Ваш подход является неправильным, temp выходит за рамки/не больше существовать, когда functon iCalculate выхода. Поэтому вы не должны возвращать адрес temp. Это будет обращение за пределы области/больше не существует переменной. Доступ к этому адресу означает неопределенное поведение.

Вы можете использовать этот подход:

void iCalculate(int x,int y,int *mult,int *divi){ 
    *mult = x*y; 
    *divi = x/y; 
} 

или вы можете использовать другой подход:

typedef struct{ 
    int mul, divi; 
} TResult; 

TResult iCalculate(int x,int y){ 
    TResult res; 
    res.mul = x*y; 
    res.divi = x/y; 
    return res; 
} 

или:

void iCalculate(int x,int y,TResult *res){ 
    res->mul = x*y; 
    res->divi = x/y; 
} 

я предлагаю первый подход. Я думаю, что слишком сложно создать новое определение структуры только для того, чтобы обернуть 2 несвязанных значения вместе.

+0

Не обязательно уничтожается, но вызывает Неопределенное поведение. Как мы все знаем, стек не заполняется нулями при выходе из функции. Извините, я просто должен был быть небольшим pendantic;) – new123456

+0

Я просто использовал логическое слово. Более правильным термином было бы то, что переменная выходит за рамки. Ничто не разрушается в C, даже освобождение от кучи не заполняет его нулем. – dragon135

1

То, как вы это сделали, неверно, так как int temp[2] исчезает после возвращения функции, поэтому у вызывающего есть указатель «свисающий». Вы должны добавить static. Другой способ, вероятно, лучше, чтобы позволить вызывающему абоненту пройти туда, где он хочет, чтобы результат был сохранен, например.

void iCalc(int x, int y, int *rp, int *rq) 
{ 
    // check if rp and rq are NULL, if so, returns 
    *rp = x*y; 
    *rq = x/y; // y != 0, and this will truncate of course. 
} 

и вызывающий абонент будет делать что-то вроде

int res[2]; 
iCalc(x, y, res, res+1); 

или аналогичный.

1

Ваш подход не был так неправильно, то вы можете вернуть адрес таблицы, как это:

int *iCalculate(int x,int y){ 
    int *temp=malloc(sizeof(int)*2); 
    temp[0]=x*y; 
    temp[1]=x/y; 
    return temp; 
} 

не забудьте освободить память:

int *result; 
result=iCalculate(10,7); 
printf("%d %d\n",result[0],result[1]); 
free(result); 
Смежные вопросы