Возвращение из функции нескольких значений

Последнее обновление: 09.09.2023

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

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

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

#include <stdio.h>
#include <assert.h>

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[] = {2, 3, 4, 5, 6, 9};
  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 <stdio.h>
#include <assert.h>

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[] = {7, 3, 4, 5, 6, 8};
  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.

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850