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

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

  • автор:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.)

Возврат значения из функции

Чистая функция, это функция, которая:

  1. является детерминированной;
  2. не обладает побочными эффектами.

int f(int x) <
int y = 0;
int z = 0;
y = 2 * x;
z = y + 1;
return z / 3;
>

Возврат нескольких разнотипных значений

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

Увы, просто так этого сделать нельзя.

Такие ситуации можно разделить на два характерных случая:

  1. Возвращаемые значения фактически представляют собой единый объект.
    Пример 1: функции getPixelColor(x, y) передаются координаты точки на текстуре, возвращается ее цвет.
  2. Возвращаемые данные не вполне связаны между собой (являются различными объектами или просто набором слабо связанных данных).
    Пример 2: функция getStudentMark() получает с клавиатуры строчку с фамилией студента и его оценку по информатике.

Пример 1

Итак, функции getPixelColor(x, y) передаются координаты точки на текстуре, надо вернуть ее цвет.

Цвет в модели RGB TrueColor описывается тремя целыми беззнаковыми числами в диапазоне от 0 до 255.

Здесь цвет точки однозначно представляет собой объект, который должен быть выделен в структуру данных.

typedef struct <
unsigned char r, g, b; //компоненты цвета red, green, blue
> tColor;

Как только создана такая Си-структура, вопрос передачи цвета из функции решен:

Пример 2

Функция getStudentMark() должна получить с клавиатуры строчку с фамилией студента и его оценку по информатике. При этом для студентов уже существует структура данных:

typedef struct <
int studentID; //идентификатор студента
char lastName[30]; //фамилия
char name[30]; //имя
unsigned int groupNumber; //номер группы
> tStudent;

Заметим, что эта структура нам для возврата значения не подходит. Мы возвращаем лишь фамилию и оценку.

Фамилия — лишь часть этой структуры данных, остальное нам в этой функции заполнить неоткуда. Заполнить пустыми значениями? А вдруг мы в месте вызова забудем, что в возвращенном экземпляре структуры правдива лишь фамилия?

Оценку по информатике можно было бы внести в эту структуру, но, согласитесь, будет странно, если оценка будет атрибутом самого студента, а не его строчки в журнале. Это не логично, особенно если учесть, что другая функция, работающая со списком студентов, будет вынуждена «выдумывать» теперь уже оценку.

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

typedef struct <
char lastName[30]; //фамилия
unsigned int mark; //оценка
> tStudentMark;

Будет хорошо, если эта структура выработана логично, и она нам еще понадобится в других функциях, тогда она «перерастет» свою одноразовость.

Функция будет выглядеть так:

tStudentMark getStudentMark()
<
tStudentMark studentMark; //локальная переменная, куда будем доставать фамилию и оценку.
//. достать фамилию и оценку (без подробностей)
return studentMark;
>

char lastName[20];
int mark;
tStudentMark studentMark; //переменная, которая нужна только для разбора значений из функции
studentMark = getStudentMark();
lastName = studentMark.lastName;
mark = studentMark.mark;

Текста получилось много, зато мы сохранили «чистоту функции».

Передача через нарушение чистоты функции

Есть еще два способа вернуть из функции значение:

  1. Передавать параметры не по значению, а по адресу, а изнутри функции просто менять их значения.
    Пример: функция getStudentMark() получает в качестве параметров адреса строки и оценки, считывает с клавиатуры строчку с фамилией студента и его оценку по информатике, и сохраняет в параметры.
  2. Сохранять возвращаемые значения в глобальных переменных.
    Стандартной функции open(filename, O_RDONLY) передается имя файла и флаги доступа, функция возвращает открывает файл, и возвращает его дескриптор (число-идентификатор, необходимое для последующих обращений к открытому файлу), однако может случиться ошибка доступа, причем код ошибки важен.

Пример

Итак, функция getStudentMark() получает в качестве параметров адрес строки и адрес оценки, считывает с клавиатуры строчку с фамилией студента и его оценку по информатике, и сохраняет в параметры.

Попробуем написать функцию с таким заголовком:

void getStudentMark(char lastName[], int *mark)
<
scanf(«%s%d», lastName, mark);
>

char lastName[20];
int mark;
getStudentMark(lastName, &mark);

Плюсы: отказались от «одноразовой» структуры данных, уменьшили длину кода.

Минусы: корректность памяти определяется местом вызова. Внутри функции хорошо бы проверять корректность данных адресов памяти.

Как вернуть через функцию два значения в C++?

Суть : Допустим у нас есть функция, в результате выполнения действий внутри нее мы получаем значения переменных, которые нам необходимо вернуть. Как это сделать? И как при вызове присвоить эти значения двум переменным одновременно?

Harry's user avatar

Vlad Kvochin's user avatar

  1. вернуть структуру или кортеж (пару) с двумя полями
  2. использовать передачу параметров по ссылке или через указатель.

Например, считать сумму и разность двух переменных:

Дополнение через 3 года 🙂 — теперь можно использовать новый вариант синтаксиса структурного связывания:

Harry's user avatar

Дополню ответ @Harry

Если под рукой компилятор с поддержкой 11 ого (и выше) стандарта, то можно воспользоваться std::tuple и вернуть его из функции, эдакое обобщение на std::pair для произвольноно числа элементов с разными типами

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.8.29.43607

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Как из функции возвращать 2 значения?

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

Точно ли в функции нужно возвращать s?
Вот прога, которая ищет в 2-х мерном массиве, т.е. матрице число строк, не содержащих 0. Точно ли в.

Очистка памяти при завершении работы функции, как правильно возвращать значения?
Я вывел для себя 2 способа возвращать значения работы функции string Add(string a1, string a2) <.

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

Добавлено через 4 минуты
& — это ссылка на перменую из основной программы, проще говоря, они означает, что в подпрограмме можно менять значения параметра)

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

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