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

#arrays #c #function

#массивы #c #функция

Вопрос:

(Мне удалось решить предыдущую проблему с выводом массива, все получилось).

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

Или я должен разбить это действие на две разные функции?

Или лучше оставить код в таком виде?

   int a2x = 0;
  int m2x = 0;
  for (i = 0; i < n; i  ) {
    if (x[i] > 0) {
      a2x = a2x   x[i];
    }
    if (x[i] < 0) {
      m2x  ;
    }
  }
  printf("n");
  printf("a2x ] n", a2x);
  printf("m2x ] n", m2x);
  int a2y = 0, m2y = 0;
  for (j = 0; j < m; j  ) {
    if (y[j] > 0) {
      a2y = a2y   y[j];
    }
    if (y[j] < 0) {
      m2y  ;
    }
  }
  printf("a2y ] n", a2y);
  printf("m2y ] n",m2y);
 

Ответ №1:

У вас может быть функция с этим типом возвращаемого значения:

 struct ReturnType
{
    int a2y;
    int m2y;
};
 

Этот тип отражает, что это пара значений, а не два экземпляра одного и того же значения. Т.е. Это X и M, а не два X и не два Ms. Он также ведет себя как копируемая переменная, например, возвращает один int .

Комментарии:

1. Зачем вам вообще создавать структуру из 2 int вместо использования массива?

2. Всякий раз, когда значения кажутся парой неидентичных семантик. Это не «X дважды» или «M дважды», это «X и M». @Davide

3. @Davide Зачем тебе вообще создавать структуру из 2 int вместо использования массива? Потому что вы можете вернуть структуру. Вы не можете вернуть массив.

4. @Davide Проблема с возвратом указателя на массив заключается в том, что вам либо нужно сделать массив статическим, что нарушает потокобезопасность, создать новый массив динамически, что означает, что вызывающий должен избавиться от него, либо попросить вызывающего передать вам указатель на массив (который вы рассмотрели в своем ответе). Когда она, наконец, преобразуется в машинные инструкции, возврат структуры или передача адреса массива, скорее всего, практически идентичны с точки зрения производительности, поэтому на данный момент это проблема стиля / предпочтений / ясности / O amp; M, которая делает ее очень контекстно-зависимой.

5. Хорошо, в любом случае семантическое назначение структуры является достаточно веской причиной для использования структуры, а не массива.

Ответ №2:

Я предлагаю вам то, что, по моему мнению, является 3 самыми простыми вариантами, которые у вас есть:

I) Выведите результат внутри функции.

Таким образом, вам не только не нужно возвращать переменные, но вы также можете объявлять их непосредственно внутри функции.

II) Передайте переменные по ссылке.

Таким образом, функция может фактически изменить их значение, так что вам не нужно ничего возвращать.

III) Выделите массив, хранящий значения, которые вы хотите вернуть, и верните массив.

Таким образом, вы можете возвращать столько значений, сколько захотите.

Редактировать: Как предложил Эндрю Хенле в комментариях к ответу Юнноса: «возврат структуры или передача адреса массива, вероятно, практически идентичны с точки зрения производительности, поэтому на данный момент это проблема стиля / предпочтений / ясности / O amp; M, которая делает ее очень контекстно-зависимой».

И поскольку, как указал Юннош, с помощью структуры вы можете придать различное значение каждому элементу, использование структуры в вашем случае более уместно.

Комментарии:

1. Если вы любезно обсудите вариант массива (с сам знаешь какими подробностями) и убедительно объясните его, я бы проголосовал за.

2. Я не хочу использовать чужие слова, но в любом случае вывод заключается в том, что использование массива эквивалентно использованию структуры, но с помощью структуры вы можете придать различное значение каждому значению. Таким образом, в случае OP структура является более подходящей. Но поскольку не так очевидно использовать структуру, а массив, вы должны добавить что-то об этом в свой ответ.

3. Вы, конечно, можете использовать ввод Эндрюса. Просто упомяните имя в ответе (это производит хорошее впечатление, я часто пробовал). Может быть, даже напишите комментарий типа «Эндрю, я полагаю, что можно улучшить мой ответ с помощью вашего ввода». чтобы они заметили. Я действительно не хочу записывать в свой ответ что-то вроде «Я рекомендую не использовать вариант, предложенный в другом ответе». В вашем ответе то же самое будет выглядеть как чистая профессиональная дискуссия, то есть быть хорошим.

4. C не поддерживает передачу чего-либо по ссылке, я думаю, вы имеете в виду передачу по указателю.

5. @12431234123412341234123 Строго говоря, вы правы. Но с большой вероятностью большинство программистов на C понимают «через указатель», когда они читают «по ссылке». Без сбоев.

Ответ №3:

Технически существует другой способ, не упомянутый ранее: передать его в большем целочисленном типе:

 #include <limits.h>

#define HIGHEST_UINT_BIT ((UINT_MAX>>1) 1)
#define HIGHEST_ULLINT_BIT ((ULLONG_MAX>>1) 1)
#if HIGHEST_ULLINT_BIT/HIGHEST_UINT_BIT/HIGHEST_UINT_BIT<2
  #error "unsigned long long int not large enough to hold 2 int variables"
#endif

//returns the integer a in higher half of the returning long long int
//and the integer b in the lower half of the returning long long
unsigned long long int foo(void)
{
  int a=42;    //set a to any integer value you like
  int b=0x42;  //same for b

  //pack a and b into the return value
  //<<(sizeof(int)*CHAR_BIT) shifts a to the higher half of r
  unsigned long long int r=((unsigned long long)a)<<(sizeof(int)*CHAR_BIT);
  r|=(unsigned)b;

  return r;
}

#include <stdio.h>

int main(void)
{
  unsigned long long int r=foo();
  //extract a and b from r
  int a=r>>(sizeof(int)*CHAR_BIT);
  int b=ramp;UINT_MAX;

  printf("a is %i (0x%X) b is %i (0x%X)n",a,(unsigned)a,b,(unsigned)b);
  return 0;
}
 

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

Комментарии:

1. Имело смысл объяснить, почему » […] никогда не следует использовать этот метод»..