Как вернуть структуру из функции c

от admin

Как вернуть структуру из функции c

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

Структура как параметр функции

При передаче структуры в качестве параметра получает копию значений структуры:

В данном случае функция print_person() принимает объект структуры person и выводит значения его элементов на консоль.

Чтобы не писать тип параметра полностью — struct person , можно определить псевдоним структуры:

Указатели на структуру как параметры

При использовании структур в качестве параметров в функции следует учитывать, что при вызове функции для структуры, также как и для параметров типа int или char, выделяется память, в которую помещаются значения элементов структуры. То есть структура в функцию передается по значению, а это значит, что переданную в функцию структуру мы изменить не можем.

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

В этом примере функция change_person принимает указатель на структуру person и увеличивает на единицу значение элемента age.

Для проверки в функции main выводим данные объекта person на консоль до и после вызова функции change_person.

Структура как результат функции

Также функция может возвращать объект структуры:

Здесь функция create_person() создает на основании полученных параметров объект структуры person и возвращает его в качестве результата.

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

Изучаю то, как структуры передаются в функции и возвращаются из функций. Такой код:

Вот дизассемблерные листинги обеих функций. Попробую их прокомментировать.

Замечаем, что функция main выделяет в стеке 16 байт, но при выравнивании стека освобождаются только 8 байт. Остальные 8 байт заняты структурой.

Еще раз посмотрим на это место в main :

С учетом адреса возврата и сохраненного ebp , адрес структуры (push eax) будет отодвинут на 3 дворда, это 0xC байт, и, видимо, обращение к адресу структуры мы наблюдаем здесь:

А что происходит дальше в makepoint ? Сложно разобраться в этом коде.

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

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

Вы с самого начала не с той стороны начали исследование. В зависимости от пожеланий компилятора, он может сделать с вашей структурой всё, что пожелает. Однако есть так называемые соглашения о вызовах, которые устанавливают ряд правил на то, как передавать параметры. Я бы на Вашем месте начал с изучение этого вопроса. Лучше сразу искать материал на английском (там это называется Calling convention). Кроме того, Вы наверное дизассемблировали код в режиме отладки, а в режиме полной оптимизации он может оказаться совсем-совсем другим. Притом даже вопрос выравнивания компилятор может решать разными способами, чтобы подсказать ему, существуют специальные директивы. Вопрос по поводу того кто выделяет память и кто её освобождает тоже решается по разному. Например, в соглашении __fastcall освобождает стек именно вызываемая функция.

Короче, я хочу сказать только то, что изучение листинга — это самый плохой из способов понять, что делает компилятор, потому что он может делать всё по-разному в разных условиях. Нужно читать документации.

Внутри функции makepoint происходит следующее

Локальная структура tmp располагается по адресу ebp — 0x8 . Соответственно код

это ни что иное как заполнение полей локальной структуры из DWORD PTR [ebp+0xc] и DWORD PTR [ebp+0x10] (параметры x и y соответственно), т.е. это

А далее идет просто копирование значения локальной структуры во внешнюю структуру-получатель, адрес которой лежит в DWORD PTR [ebp+0x8]

Далее, согласно calling convention, адрес получателя еще и возвращается в eax

Ваше предположение по поводу

не верно (если я его правильно понял).

Читать:
Как посмотреть код 1с

На вершину стека перед вызовом makepoint были положены значения x , y и указателя на структуру-приемник результата. Выход из makepoint был сделан по ret 4 . Эта инструкция удалила из стека адрес структуры-получателя, но оставила аргументы x и y в стеке. Инструкция add esp,0x8 удаляет из стека эти аргументы x и y , которые вместе занимают 8 байт.

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

В этом посте будет обсуждаться, как вернуть несколько значений из функции в C.

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

1. Указатели в C

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

результат:

a = 10, b = 20, c = A

2. Структуры в C

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

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

результат:

a = 10, b = 20, c = A

3. Массив

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

результат:

a = 10, b = 20, c = 30

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

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

Также см:

Оценить этот пост

Средний рейтинг 4.69 /5. Подсчет голосов: 49

Голосов пока нет! Будьте первым, кто оценит этот пост.

Сожалеем, что этот пост не оказался для вас полезным!

Расскажите, как мы можем улучшить этот пост?

Спасибо за чтение.

Пожалуйста, используйте наш онлайн-компилятор размещать код в комментариях, используя C, C++, Java, Python, JavaScript, C#, PHP и многие другие популярные языки программирования.

Как мы? Порекомендуйте нас своим друзьям и помогите нам расти. Удачного кодирования ��

Структура в функцию в С++ как передать и вернуть

В этой статье вы найдете соответствующие примеры для передачи структур в качестве аргумента функции и использования их в своей программе на C++. Структурные переменные могут быть переданы в функцию и возвращены аналогично обычным аргументам.

Структурную переменную можно передать функции так же, как и обычный аргумент. Рассмотрим этот пример:

Пример 1

В этой программе пользователя просят ввести Name (имя), Age (возраст) и Salary (зарплату) человека внутри функции main().

Затем структурная переменная p передается функции с использованием:

Тип возвращаемого значения displayData() является недействительным, и передается единственный аргумент структуры типа Person .

Затем из этой функции выводятся члены структуры p.

Пример 2: Возврат структуры из функции

Результат этой программы такой же, как и у программы выше.

Структурная переменная p структуры типа P erson определена в функции main().

Структурная переменная p передается функции getData(), которая принимает ввод от пользователя и возвращается в основную функцию.

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

Затем структурная переменная p передается в функцию displayData(), которая отображает информацию.

Похожие статьи