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

Важны: Пожалуйста, посмотрите этот очень связанный вопрос: Возврат нескольких значений в C ++.

Я хочу узнать, как сделать то же самое в ANSI C? Вы бы использовали struct или передали адреса параметров в функции? Мне нужен чрезвычайно эффективный (быстрый) код (время и пространство), даже ценой читабельности.

РЕДАКТИРОВАТ: Спасибо за ответы на все вопросы. Хорошо, я думаю, что должен кое-что объяснить: я пишу эту книгу об определенном подмножестве алгоритмов для определенной области. Я поставил перед собой совершенно произвольную цель создания наиболее эффективных (временных и пространственных) реализаций для всех моих алгоритмов, размещаемых в сети, за счет читабельности и прочего. Это отчасти характер моего (общего) вопроса.

Отве: Я надеюсь, что получу это прямо, от (возможно) быстрее всего к более здравому смыслу (все это априори, то есть без тестирования):

Сохранять значения в глобальном объекте (я бы предположил что-то вроде outvals [2]?) Или Передать значения в виде параметров в функции (foo (int in, int * out1, int * out2)) или вернуть структуру с обоими выходами или (3) только если значения семантически связаны.

Имеет ли это смысл? Если так, то я думаю, что ответ Джейсона - самый близкий, хотя все они обеспечивают некоторую часть «загадки». У Роберта все в порядке, но в настоящее время семантика - не то, что мне нужно (хотя его совет должным образом отмечен)

Спасибо вам всем

 Jonathan Leffler07 июл. 2009 г., 15:56
В C нотация для «ответа 2» с использованием «foo (int in, int & out1, int & out2)» не имеет смысла - ссылки на C ++, но не на C.
 Jonathan Leffler07 июл. 2009 г., 16:01
Обычно книги выиграют, если ясность будет главной целью, а производительность пространства и времени - вторичной. Как вы справляетесь с напряженностью между пространством и временем - самый эффективный алгоритм зачастую не самый эффективный по времени? Если у вас уже есть два алгоритма, почему бы не создать ясный, простой и надежный алгоритм? (Один ответ против 3 вариантов заключается в том, что слишком много вариантов.)
 Dervin Thunk06 июл. 2009 г., 22:12
Это тоже хороший совет. Спасибо. (Кстати, я вас голосовал, так получилось, что я получил гораздо более практичный ответ, вот и все.)
 Robert Cartaino♦07 июл. 2009 г., 03:19
Я знаю. Спасибо
 Robert Cartaino♦06 июл. 2009 г., 21:55
Напиши свой код и профиль безжалостно. Я думаю, вы обнаружите, что влияние struct-vs-reference на производительность является так крошечный по сравнению с остальной частью вашей реализации, что даже не стоит принимать во внимание.

Ответы на вопрос(11)

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

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

 anon06 июл. 2009 г., 21:06
Для редакторов - при внесении исправлений, пожалуйста, будьте уверены в своем правописании.
 Dervin Thunk06 июл. 2009 г., 20:54
Я понимаю. Просто начал C и хотел знать, есть ли лучший способ. Вы сказали бы, что структуры более дороги чем альтернатив
 Dervin Thunk06 июл. 2009 г., 22:31
GMan, спасибо за совет учебника, но на этом этапе моей карьеры, я могу заверить вас, я могу беспокоиться об обоих одновременно. :)
 anon06 июл. 2009 г., 21:09
@ Dervin Вероятно, нет большой разницы в производительности между этими двумя вариантами, но это будет зависеть от того, как вы используете структуру и т. Д., О которых у нас нет подробностей. Если производительность так важна (и, честно говоря, редко бывает), тогда вам нужно выполнить свои собственные измерения, чтобы определить, какой из них самый быстрый.

и он также должен быть быстрым, щелчки и нажатия дешевы:

void somefunction (int inval1, int inval2, int *outval1, int *outval2) {
   int x = inval1;
   int y = inval2;
// do some processing
   *outval1 = x;
   *outval2 = y;
   return;
}
 Dervin Thunk06 июл. 2009 г., 21:01
ты имеешь в виду & outval1, int & outval2?
 mtasic8507 июл. 2009 г., 19:56
это нормально, но, пожалуйста, выделите свой код
 KevinDTimm06 июл. 2009 г., 21:34
no. Я написал именно то, что имел в виду.

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

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

Решение Вопроса

Чтобы избежать затрат на передачу чего-либо, используйте глобальный. Следующим лучшим является единственная структура, переданная указателем / ссылкой. После этого идут отдельные указатели / ссылочные параметры.

Однако, если вам нужно упаковать данные в структуру и затем прочитать их обратно после вызова, вам может быть лучше передать отдельные параметры.

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

которая будет возвращена, не сложна, то и передача адресов к значениям тоже будет работать.

Лично все сводится к тому, насколько грязным будет интерфейс.

void SomeFunction( ReturnStruct* myReturnVals )
{
  // Fill in the values
}   

// Do some stuff    
ReturnStruct returnVals;
SomeFunction( &returnVals);    
// Do more stuff
 Johannes Schaub - litb06 июл. 2009 г., 21:44
Я рад, что он удалил это. Нет ничего плохого в возврате структуры из функции в C. На самом деле это вызвало путаницу.
 KevinDTimm06 июл. 2009 г., 21:41
@ Су Вэй Тан - нет, вы были правы насчет памяти, выделенной внутри функции (и это плохо) - вам не нужно было ее удалять, речь идет об обучении правильной работе.
 Mike Cooper06 июл. 2009 г., 21:29
Извините за невежество, я пока немного знаю C. Почему возврат локальной копии структуры плохой?
 Soo Wei Tan06 июл. 2009 г., 21:35
На самом деле, это было бы неплохо, если бы вы не указывали на память, выделенную внутри функции. Я просто собираюсь убрать этот блок, чтобы уменьшить путаницу.

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

 quant_dev06 июл. 2009 г., 21:22
Не обязательно, если глобальные объекты нужно извлечь в кеш.

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

Мои личные предпочтения - возвращать динамически распределенную (malloc'd) структуру. Я избегаю использования аргументов функции для вывода, потому что я думаю, что это делает код более запутанным и менее поддерживаемым в долгосрочной перспективе.

 Jonathan Leffler07 июл. 2009 г., 15:58
Динамически распределенный означает, по крайней мере, потенциал утечки памяти. Это означает, что пользователи вашей функции должны быть намного осторожнее.

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

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

И всем, кто предлагает ссылки, хорошо, что ОП сказал «C», а у C их нет (ссылки).

И сладкий пернатый Иисус, могу ли я завтра проснуться и не смотреть по телевизору ничего о Короле Флопе?

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

Ваш ответ на вопрос