Как вернуть два значения из функции c
Перейти к содержимому

Как вернуть два значения из функции c

  • автор:

Как вернуть два значения из функции c

Функция в C может возвращать только одно значение. Тем не менее, что если нам надо получить из функции сразу несколько значений? В этом случае мы можем использовать разные подходы. Основные из них — возвращение комплексного объекта, который инкапсулирует отдельные значения, либо использование выходных параметров.

Объединение возвращаемых значений

Наиболее простой способ возвратить из функции несколько значений — это определить структуру для хранения этих значений и возвратить ее. Например, нам надо получить из массива минимальное и максимальное значения. Для этого мы могли определить функцию, которая возвращает структуру с двумя значениями:

#include #include typedef struct < int min; int max; >MinMax; MinMax getMinMax(int* array, size_t length) < assert(length >1 && "Array length is invalid"); MinMax result; result.min = array[0]; result.max = array[0]; for(size_t i = 0; i < length; i++) < if(array[i] < result.min) result.min = array[i]; if(array[i] >result.max) result.max = array[i]; > return result; > int main(void) < int array[] = ; size_t length = sizeof(array) / sizeof(int); MinMax data = getMinMax(array, length); printf("min=%d\n", data.min); // min=2 printf("max=%d\n", data.max); // max=9 >

Здесь для возвращения из функции минимального и максимального значения массива определена структура MinMax, которую возвращает функция getMinMax. Это наиболее простой и очевидный способ возвращения нескольких значений. Однако он имеет свои минусы. Прежде всего нам надо специально определять структуру под возвращаемые значения. Во-вторых, при возвращении структуры происходит копирование ее значений в стеке, что увеличивает объем потребляемой памяти.

Выходные параметры

Другой способ возвратить из функции несколько значений представляют выходные параметры (out-параметры). Язык Си как таковой не имеет концепции выходных параметров функции (как например, C#), однако мы можем симулировать выходные параметры с помощью указателей:

#include #include void getMinMax(int* array, size_t length, int* min, int* max) < assert(length >1 && "Array length is invalid"); *min = array[0]; *max = array[0]; for(size_t i = 0; i < length; i++) < if(array[i] < *min) *min = array[i]; if(array[i] >*max) *max = array[i]; > > int main(void) < int array[] = ; size_t length = sizeof(array) / sizeof(int); int minVal = 0; int maxVal = 0; getMinMax(array, length, &minVal, &maxVal); printf("min=%d\n", minVal); printf("max=%d\n", maxVal); >

Общий механизм определения и передачи выходных параметров заключается в следующем. Во-первых, определяем в функции параметры-указатели:

void getMinMax(int* array, size_t length, int* min, int* max)

Здесь параметры-указатели min и max как представляют выходные параметры. Внутри функции нам не важны их начальные значения. Наоборот, функция устанавливает их значения.

При вызове функции определяются переменные, и их адреса передаются выходным параметрам:

int minVal = 0; int maxVal = 0; getMinMax(array, length, &minVal, &maxVal);

В данном случае выходным параметрам min и max передаются соответственно адреса переменных minVal и maxVal.

При использовании выходных параметров нам не обязательно определять дополнительные структуры. Мы избегаем изличнего копирования возвращаемых значений в стеке. Однако выходные параметры рахдувают определение функции, могут снизить ее читабельность, особенно когда таких параметров много.

Как вернуть несколько значений из функции?

Здравствуйте, пытаюсь написать функцию для генерации чисел, и надо вернуть 3 переменные из функции. Но получается вернуть только одну. Как вернуть несколько переменных из функции в С++?

#include #include using namespace std; int generator() < random_device random_device; mt19937 generator(random_device()); uniform_int_distribution<>distribution(1, 10); int x = distribution(generator); int c = distribution(generator); int answer = x * c; return answer, x, c; > int main()
  • Вопрос задан более года назад
  • 879 просмотров

Комментировать
Решения вопроса 1
Wataru @wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.

Кроме параметров функции, можно возвращать структуру с именованными значениями или std::vector или std::touple.

Ответ написан более года назад
Нравится 2 6 комментариев
Anonymous @Nikita1244 Автор вопроса

Проблема в том, что предложенное ранее решение не работает.
Про ваше решение можете немного понятнее объяснить, пожалуйста?

Wataru @wataru Куратор тега C++
Никита Савченко, Чего там не работает-то?
Тип функции сделайте s td::vector . Возвращайте
Anonymous @Nikita1244 Автор вопроса
Wataru, я как новичок. Не пойму все равно, что означает ваш std::vector? Погуглил, не понял.
Wataru @wataru Куратор тега C++

Никита Савченко, Это тип. Как int, bool, или char*. std::vector — это класс, который хранит массив int в c++.

Anonymous @Nikita1244 Автор вопроса
Wataru, спасибо, попробую обязательно.
Anonymous @Nikita1244 Автор вопроса

Дошли руки посмотреть Ваше решение, и действительно, решение Александра Ананьева выглядит не элегантно, и оно устарело(Использовалось в последний раз как не-легаси код, судя по всему, в С++ 11).
Сейчас действительно используют std::vector, std::touple

Ответы на вопрос 1

Можно вернуть через параметры функции
void generator(int& answer, int& x, int& c)

#include #include using namespace std; void generator(int& answer, int& x, int& c) < random_device random_device; mt19937 generator(random_device()); uniform_int_distribution<>distribution(1, 10); x = distribution(generator); c = distribution(generator); answer = x * c; > int main()

Ответ написан более года назад
Нравится 2 11 комментариев
Anonymous @Nikita1244 Автор вопроса
возвращает в любом случае тогда 1. И ничего более.
Anonymous @Nikita1244 Автор вопроса
не работает в общем-то ваше решение, к сожалению 🙁
Никита Савченко, оно не может не работать. Покажи свой код.
Anonymous @Nikita1244 Автор вопроса

#include #include using namespace std; void generator(int& answer, int& x, int& c) < random_device random_device; mt19937 generator(random_device()); uniform_int_distribution<>distribution(1, 10); int x = distribution(generator); int c = distribution(generator); int answer = x * c; return answer, x, c; > int main()

Евгений Шатунов @MarkusD Куратор тега C++

не работает в общем-то ваше решение

Да нет, решение работает. Только Саша, по своему обыкновению, не подумав написал первое что ему в гугле попалось.

При передаче по ссылке тебе не надо возвращать значения, они доступны внутри функции для прямого изменения. Это — сублимация возврата нескольких значений, используемая в палеозойской древности стандарта C++98.
Настоящий возврат набора значений описан только в ответе Wataru.

Но вот в чем дело.
Код return answer, x, c; не должен был родиться в твоем мозгу для функции с типом результата void . Написанное тобой в примере выдает твою полную безграмотность в языке. Даже большую, чем у Саши.
И в этом плане настоящий возврат нескольких значений для тебя просто недосягаем, потому что ты просто не проходишь по знаниям для его использования. Ты ведь даже не знаешь, какой конкретно стандарт C++ ты используешь. А ведь именно от этого зависит решение твоего вопроса.

#include #include using namespace std; void generator(int& answer, int& x, int& c) < random_device random_device; mt19937 generator(random_device()); uniform_int_distribution<>distribution(1, 10); x = distribution(generator); c = distribution(generator); answer = x * c; > int main()

Anonymous @Nikita1244 Автор вопроса

Александр Ананьев, Отредактируй немного ответ, добавив этот код(пусть чисто пример будет в ответе), чтобы людям не копаться в комментариях. Отмечу решением.

Anonymous @Nikita1244 Автор вопроса

Ты ведь даже не знаешь, какой конкретно стандарт C++ ты используешь.

Никогда не думал, что стандарты влияют настолько сильно. Стандарт использую — С++ 17. Хорошо, посмотрю ответ Wataru. Как я понял, решение, которое написал Александр Ананьев, является устаревшим.

Anonymous @Nikita1244 Автор вопроса

Код return answer, x, c; не должен был родиться в твоем мозгу для функции с типом результата void

Тут уже мой косяк, да, но я удалял и код все равно не работал 🙂
Только вот я пробовал по разному писать и всю эту чепуху вам прислал. Так-то да, ретурна судя по всему не должно быть, ибо компилятор и IDE ругаются на него и говорят что ретурна не может быть в void-функции.

Евгений Шатунов @MarkusD Куратор тега C++

Стандарт использую — С++ 17.

Да, стандарт языка кардинально влияет на доступные возможности. Смотри вот.

Допустим у тебя есть твоя std::tuple generator() . Это то, о чем написал Wataru. Принять результат ты можешь в такой же кортеж (C++11), можешь воспользоваться обобщением и инициализацией копией (C++11), а можешь воспользоваться std::tie [?] для C++14 или структурным связыванием из C++17.
И все будет зависеть именно от используемого тобой стандарта языка.

И вот, в C++17 у тебя получится такой код:

int main()

При том условии, что ты правильно воспользуешься техникой NRVO, структурное связывание у тебя не приведет к скрытому копированию значения, а все три поля из main будут сразу инициализированы внутри generator .

Как вернуть два значения из функции c

С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:
#include
#define Numer 7
int main(void)
int massiv( int * ogo , int ugu );
int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >;
int raz;
raz = massiv( res , Numer );
printf(«Вывод значений «);
>

int massiv( int * ogo , int ugu )
.
return Что_Либо_Только_Одно_Значение;
>
Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 17.02.02 15:06
Оценка:

Извените в начале забыл отформатироваьт текст.

С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:

#include #define Numer 7 int main(void) int massiv( int * ogo , int ugu ); < int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >; int raz; raz = massiv( res , Numer ); printf("Вывод значений "); > int massiv( int * ogo , int ugu )

Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re: Функция и возвращение 2-х значений ? Начинающий.

От: Kaa http://blog.meta.ua/users/kaa/
Дата: 17.02.02 15:19
Оценка: 3 (1)

Здравствуйте Mr-Twister, Вы писали:

MT>С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
MT>В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:

MT>#include MT>#define Numer 7 MT>int main(void) MT>int massiv( int * ogo , int ugu ); MT> < MT>int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >; MT> int raz; MT> raz = massiv( res , Numer ); MT> printf("Вывод значений "); MT>> MT>int massiv( int * ogo , int ugu ) MT> < MT>. MT> return Что_Либо_Только_Одно_Значение; MT>>

MT>Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

Сначала о задании: нигде в нем (в том фрагменте, что ты привел) не сказано, что надо вернуть 2 значения. Сказано: «разность», что есть одно число. А именно, ArrMac — ArrMin = то, что тебе надо вернуть (первдарительно посчитав эти самые ArrMax && ArrMin).

По сути вопроса, оторвавшись от этого конкретного задания:

Есть такая штука в С++, как передача параметров по ссылке. Этот способ в числе прочих преимуществ, о которых здесь пока говорить не будем, дает и такое: появляется возможность изменения значения переменной, объявленной в программе, внутри некоторой функции. Таким образом, появляется возможность определить у функции СКОЛЬКО УГОДНО много возвращаемых значений. Единственное, что отличает этот способ от обычного возврата значения функцией, что это делается не обычной семантикой типа y=f(x), а подругому.

int arg1 = 0, arg2 = 1, arg3 = 1; int FuncMultipleRet( int& a1, int& a2, int& a3 ) < a1 += a2 + a2; a2 += a1 + a3; a3 += a1 + a2; >void main() < printf( "%d, %d, %d\n", arg1, arg2, arg3 )l FuncMultipleRet( arg1, arg2, arg3 ); printf( "%d, %d, %d\n", arg1, arg2, arg3 )l >

В приведенном примере функция делает некоторые вычисления, при этом меняя значения своих аргументов. По окончании функции значения аргументов изменятся, тогда как, если бы они передавались по значения (а не по ссылке), по изменения внутри функции делалиcь бы с локальной копией аргументов, и значения argi не изменились бы по выходе их функции.

Алексей Кирдин
Re[2]: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 17.02.02 15:24
Оценка:

Здравствуйте Kaa, Вы писали:

Kaa>Есть такая штука в С++, как передача параметров по ссылке. Этот способ в числе прочих преимуществ, о которых здесь пока говорить не будем, дает и такое: появляется возможность изменения значения переменной, объявленной в программе, внутри некоторой функции. Таким образом, появляется возможность определить у функции СКОЛЬКО УГОДНО много возвращаемых значений. Единственное, что отличает этот способ от обычного возврата значения функцией, что это делается не обычной семантикой типа y=f(x), а подругому.

Понял Спасибо , а я чего -то и не подумал про изменения параметров по ссылке . Спасибо!

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re[2]: Функция и возвращение 2-х значений ? Начинающий.

От: Kaa http://blog.meta.ua/users/kaa/
Дата: 17.02.02 15:26
Оценка:

Здравствуйте Mr-Twister, Вы писали:

MT>Извините в начале забыл отформатироваьт текст.

#include

Используй для лучшего эстетического восприятия тэг ccode для кода. написянного на C/C++:

#include 

Так красивше будет.

Алексей Кирдин
Re[3]: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 17.02.02 15:31
Оценка:

Здравствуйте Kaa, Вы писали:

Kaa>Так красивше будет.

Окей, буду така делать, правда уже в следующем вопросе.
Еще раз Спасибо.

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re: Функция и возвращение 2-х значений ? Начинающий.

От: Brother
Дата: 17.02.02 15:41
Оценка: 3 (1)

Здравствуйте Mr-Twister, Вы писали:

MT>С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
MT>В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал

Есть несколько вариантов.
Например, возвращай структуру типа такой
struct Diff
int minDiff;
int maxDiff;
>
как то так.

Diff massiv( int * ogo , int ugu)
.
Diff res;
res.minDiff = . ;
res.maxDiff = . ;
return res;
>

Или передавай по ссылке две переменных, в которых будешь возвращать результат, как-то так
void massiv( int * ogo , int ugu, int& diffMin, int& diffMax )
<
.
diffMin = . ;
diffMax = . ;
>

С уважением,
Сергей
Re[2]: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 17.02.02 15:44
Оценка:

Здравствуйте Brother, Вы писали:

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re: Функция и возвращение 2-х значений ? Начинающий.

От: Кодт
Дата: 18.02.02 08:17
Оценка:

Здравствуйте Mr-Twister, Вы писали:

MT>С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
MT>В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:
MT>#include
MT>#define Numer 7
MT>int main(void)
MT>int massiv( int * ogo , int ugu );
MT> <
MT> int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >;
MT> int raz;
MT> raz = massiv( res , Numer );
MT> printf(«Вывод значений «);
MT>>

MT>int massiv( int * ogo , int ugu )
MT> <
MT> .
MT> return Что_Либо_Только_Одно_Значение;
MT>>

MT>Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

(Ниже я заменил тип данных на double, чтобы не перепутать значения с индексами)

Способ первый
Сделать функцию с 2 out-параметрами

double Distance(/*in*/ double* data, int length, /*out*/ int* index1, int* index2) < . *index1 = index_of_least; *index2 = index_of_greatest; return data[index_of_greatest] - data[index_of_least]; >
double Distance(/*in*/ const double* data, int length, /*out*/ int& index1, int& index2) < . index1 = index_of_least; index2 = index_of_greatest; return data[index_of_greatest] - data[index_of_least]; >

Pascal/Delphi

function Distance(data:^real; length:integer; var index1:integer; var index2:integer):real;

Способ второй
(пригоден только для С++)
Возвращать объект

struct DISTANCE < int least, greatest; double distance; >; DISTANCE Distance(const double* data, int length) < DISTANCE d; . return d; >

Перекуём баги на фичи!
Re[2]: Функция и возвращение 2-х значений ? Начинающий.

От: Аноним
Дата: 18.02.02 08:36
Оценка:

Здравствуйте Кодт, Вы писали:

К>Здравствуйте Mr-Twister, Вы писали:

MT>>С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
MT>>В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:
MT>>#include
MT>>#define Numer 7
MT>>int main(void)
MT>>int massiv( int * ogo , int ugu );
MT>> <
MT>> int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >;
MT>> int raz;
MT>> raz = massiv( res , Numer );
MT>> printf(«Вывод значений «);
MT>>>

MT>>int massiv( int * ogo , int ugu )
MT>> <
MT>> .
MT>> return Что_Либо_Только_Одно_Значение;
MT>>>

MT>>Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

К>(Ниже я заменил тип данных на double, чтобы не перепутать значения с индексами)

К>Способ первый
К>Сделать функцию с 2 out-параметрами

К>C:
К>

К>double Distance(/*in*/ double* data, int length, /*out*/ int* index1, int* index2) К> < К>. К> *index1 = index_of_least; К> *index2 = index_of_greatest; К> return data[index_of_greatest] - data[index_of_least]; К>> К>
К>double Distance(/*in*/ const double* data, int length, /*out*/ int& index1, int& index2) К> < К>. К> index1 = index_of_least; К> index2 = index_of_greatest; К> return data[index_of_greatest] - data[index_of_least]; К>> К>

К>Pascal/Delphi
К>

К>function Distance(data:^real; length:integer; var index1:integer; var index2:integer):real; К>

К>Способ второй
К>(пригоден только для С++)
К>Возвращать объект
К>

К>struct DISTANCE К> < К>int least, greatest; К> double distance; К>>; К>DISTANCE Distance(const double* data, int length) К> < К>DISTANCE d; К> . К> return d; К>> К>

А разве Pascal и С не позволяют возвращать структуры.

Re[2]: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 18.02.02 10:20
Оценка:

Здравствуйте Кодт, Вы писали:

Спасибо Кодт за ответ, но Вы меня немножко не поняли. Может я плхо задал, но это бывает.
Я имел в виду возвращать значение не с вычислением его в команде return.
А вернуть одновременно два значения сразу, к примеру Max и Min без вычисления.
Я знаю,что можно по ссылке изменить значение без всякого возврата, но в начале хотел выяснить может существует возврат сразу двух значений к одной переменной, в которой была вызвана ф-я. raz = massiv( res , Numer );
А потом эти 2-а значения распределить по двум переменным .

дас ист нихьт фантастиш, дас ист руссиш Ванюшка
Re[3]: Функция и возвращение 2-х значений ? Начинающий.

От: Кодт
Дата: 18.02.02 10:55
Оценка:

Здравствуйте Mr-Twister, Вы писали:

MT>Спасибо Кодт за ответ, но Вы меня немножко не поняли. Может я плхо задал, но это бывает.
MT>Я имел в виду возвращать значение не с вычислением его в команде return.
MT>А вернуть одновременно два значения сразу, к примеру Max и Min без вычисления.
MT>Я знаю,что можно по ссылке изменить значение без всякого возврата, но в начале хотел выяснить может существует возврат сразу двух значений к одной переменной, в которой была вызвана ф-я. raz = massiv( res , Numer );
MT>А потом эти 2-а значения распределить по двум переменным .

Если требуется найти минимальную и максимальную разности (а я думал — индексы элементов) — то подходы остаются те же.
1) через out-параметры
2) через структуру

Эти параметры можно устанавливать как в конце, так и в процессе работы функции.
(просто — один раз в конце — будет быстрее и очевиднее).

Если же хочется сделать так, что функция все еще работает, а клиент уже получил какие-то данные — то это, звините, многопоточность. (тут возможны варианты)

Перекуём баги на фичи!
Re: Функция и возвращение 2-х значений ? Начинающий.

От: sluge
Дата: 18.02.02 11:02
Оценка:

Здравствуйте Mr-Twister, Вы писали:

MT>С функциями возвращающими одно значение разобрался. Но как бы вернуть 2-а значения ?
MT>В задании написано создать ф-ю, которая возвращает разность между наибольшим и наименьшим элементаим в массиве значений. Ну одно значение возвращенное это вроде как я сделал:
MT>#include
MT>#define Numer 7
MT>int main(void)
MT>int massiv( int * ogo , int ugu );
MT> <
MT> int res[Numer] = < 12, 23, 43, 32, 3, 34, 32 >;
MT> int raz;
MT> raz = massiv( res , Numer );
MT> printf(«Вывод значений «);
MT>>

MT>int massiv( int * ogo , int ugu )
MT> <
MT> .
MT> return Что_Либо_Только_Одно_Значение;
MT>>
MT>Помогите как в одной ф-ии вернуть сразу два разных значения, или все же придется делать две разные ф-ии ?

Попробуй сделать так: напиши функцию, которая будет принимать в качестве параметра кроме массива и его длинны специальный параметер, который будет определять, что возвращать-минимум иил максимум. Удачи

Re[4]: Функция и возвращение 2-х значений ? Начинающий.

От: Mr-Twister http://cosmozo.narod.ru/
Дата: 18.02.02 11:11
Оценка:

Здравствуйте Кодт, Вы писали:

Окей, вроде эту тему уже разжевал, поехал я дальше учит C
СЭНКС ВСЕМ! 🙂

вернуть Несколько значений из функции в C

Нужно возвратить из функции значения 2х переменных. На ум приходит только идея сделать массив с этими значениями и через return выдать указатель на него. Но может есть другой способ?

vdm ★★
28.12.06 05:20:13 MSK

Не нравится мне твоё «сделать массив», сдаётся мне что ты собрался ссылку на локальный массив возвращать. 🙂 Очень не рекомендую. 🙂

Вообще обычно в таких случаях функции передают указатель на массив или структуру, в которую она пишет результаты. А возвращает она в таком случае просто код завершения (типа успешно/неуспешно). См., например, man 2 fstat.

Teak ★★★★★
( 28.12.06 05:25:30 MSK )
Ответ на: комментарий от Teak 28.12.06 05:25:30 MSK

typedef struct < int one, int two >retval2; retval2 * f(. ) < retval2 * retval = NULL; . if (!error) < retval = malloc(sizeof(retval2)); retval->one = one; retval->two = two; > return retval; > int main(. ) < retval2 * retval; if (retval = f(. )) < printf("one = %i, two = %i\n", retval->one, retval->two); free(retval); > > --- что нить типа такого в голову не приходило. )))

Ex ★★
( 28.12.06 09:01:16 MSK )

> Нужно возвратить из функции значения 2х переменных. На ум приходит > только идея сделать массив с этими значениями и через return выдать > указатель на него. Но может есть другой способ? Так можно делать только если массив статический: int *foo() < static int a[] = ; return a; > Второй способ вернуть структуру: struct S foo(char c, double d) < struct S s; s.ch = c; s.dl = d; return s; >Третий способ, который обычно применяется во всех библиотеках, объявить массив или структуру во внешнем блоке и передавать в функцию их адреса.

shumer ★
( 28.12.06 09:40:31 MSK )

Можно возвращать структуру, но считается, что это не оч. хорошо, т.к. вся структура укладывается в стек: typedef struct < int one; int two; >retval2; retval2 f() < retval2 x; x.one=1; x.two=2; return x; >int main(int argc, char **argv) < retval2 y; y=f(); >Выделять память внутри функции считается не оч. правильным путём, насколько я понимаю. Так что наиболее правильным является передача функции указателя на структуру (или массив): typedef struct < int one; int two; >retval2; int f(reval2 *x) < x->one=1; x->two=2; return 1; //код возврата=всё ок > int main(int argc, char **argv) < retval2 y; if (!f(&y)) //обработка ошибки >

Davidov ★★★★
( 28.12.06 10:17:07 MSK )
Ответ на: комментарий от Davidov 28.12.06 10:17:07 MSK

>> Выделять память внутри функции считается не оч. правильным путём, насколько я понимаю. Так что наиболее правильным является передача функции указателя на структуру (или массив):

не спорю, попросили привести пример, мну привел то что первое в голову пришло )

Ex ★★
( 28.12.06 10:49:02 MSK )
Ответ на: комментарий от Ex 28.12.06 10:49:02 MSK

>не спорю, попросили привести пример, мну привел то что первое в голову пришло )

Да не, никаких претензий. Сам так иногда делаю. Более того, по-моему, в каких-то стандартных вызовах было нечто подобное.

Я так понимаю, что логика состоит в том, что выделением памяти и её освобождением должны быть в логически эквивалентных местах.

То есть, например, в случае наличия функций retval2 *alloc_s1() и int free_s2(retval2 *r), всё уже хорошо. Вот и пример, где это может быть оправдано.

Кстати, всё это уже начинает смахивать на ООП.

Davidov ★★★★
( 28.12.06 10:57:57 MSK )
Ответ на: комментарий от Davidov 28.12.06 10:57:57 MSK

таки ООП это парадигма программирования и не зависит от конкретной реализации в ЯВУ

Ex ★★
( 28.12.06 11:05:00 MSK )
Ответ на: комментарий от shumer 28.12.06 09:40:31 MSK

>Так можно делать только если массив статический: >int *foo() > < >static int a[] = ; > return a; >> Только надо быть очень аккуратным: при повторном вызове будет возвращён тот же указатель.

Davidov ★★★★
( 28.12.06 11:10:25 MSK )
Ответ на: комментарий от Davidov 28.12.06 11:10:25 MSK

>>Так можно делать только если массив статический:

>>int *foo() >>< >> static int a[] = ; >> return a; >>>

>Только надо быть очень аккуратным: при повторном вызове будет возвращён >тот же указатель.

Еще это несколько не thread-safe

anonymous
( 28.12.06 15:08:24 MSK )

void test_retval (int a,int b, int c, int *ret1,int *ret2) < . *ret1=. ; *ret2=. ; >. int r1,r2 test_reatval(1,2,3,&r1,&r2); .

xnix ★★
( 28.12.06 16:25:14 MSK )
Ответ на: комментарий от Ex 28.12.06 09:01:16 MSK

Ну и нахрена звать malloc без необходимости? Если только чтоб выпендриться.

Teak ★★★★★
( 28.12.06 17:38:44 MSK )
Ответ на: комментарий от shumer 28.12.06 09:40:31 MSK

> Так можно делать только если массив статический:

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

Teak ★★★★★
( 28.12.06 17:40:11 MSK )
Ответ на: комментарий от Teak 28.12.06 17:40:11 MSK

> ужоснах, не слушайте его, дети. 🙂 функция станет нереентрабельной, приглашаю всех в гугль на тему чем это грозит.

Конечно так делать не следует, хотя и возможно. Вобщем я сказал «can», а ты имел ввиду «may» 🙂

Блин, простой вопрос растянули уже на чертову дюжину постов. Короче, vdm, передавай в функцию адрес структуры с двумя полями и не парься. Все остальное грязный хак.

shumer ★
( 28.12.06 17:52:21 MSK )
Ответ на: комментарий от shumer 28.12.06 17:52:21 MSK

Согласен, все посты в этой теме, кроме первого, моего, — лишние. 🙂

Teak ★★★★★
( 28.12.06 18:02:01 MSK )
Ответ на: комментарий от Teak 28.12.06 17:38:44 MSK

ув. тов. Teak прочтите пост выше.

Ex ★★
( 28.12.06 18:07:45 MSK )
Ответ на: комментарий от Ex 28.12.06 18:07:45 MSK

> ув. тов. Teak прочтите пост выше.

Не, Ex, извини, но ты там фигню написал. Заморачиваться со структурой в функции стоит только если ты ее всю будешь возращать (структурка небольшая). А создавать ее динамически, а потом возвращать указатель, имхо хреновая идея. Кто-то использующий твою функцию должен знать и помнить о том, что ему где-то free надо втыкать, лишний, тяжелый malloc, и ради чего все?

shumer ★
( 28.12.06 18:51:10 MSK )
Ответ на: комментарий от Teak 28.12.06 18:02:01 MSK

> Согласен, все посты в этой теме, кроме первого, моего, — лишние. 🙂

ты не указал решение с возвратом структуры. Оно непопулярно, потому что этого не было в ранних компиляторах и про это не написано в К&Р Но для 2-х полей оно оптимально

dilmah ★★★★★
( 28.12.06 18:59:37 MSK )
Ответ на: комментарий от dilmah 28.12.06 18:59:37 MSK

> Оно непопулярно, потому что этого не было в ранних компиляторах и про это не написано в К&Р

Вот хохма на эту тему, совершенно случайно наткнулся:

2.2: I heard that structures could be assigned to variables and passed to and from functions, but K&R I says not.

K&R I was wrong; they hadn’t actually learned C very well before writing the book. Later, Ritchie got a job at Bell Labs, and worked closely with the authors of C, allowing the 2nd edition of the book to be much more accurate. (Kernighan already worked at Bell Labs, as a video game developer.)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *