Как передать структуру в функцию c
Перейти к содержимому

Как передать структуру в функцию c

  • автор:

Как передать структуру в функцию c

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

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

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

#include struct person < char* name; int age; >; void print_person(struct person user) < printf("Name: %s \n", user.name); printf("Age: %d \n", user.age); >int main(void) < struct person tom = ; print_person(tom); return 0; >

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

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

#include typedef struct < char* name; int age; >person; void print_person(person user) < printf("Name: %s \n", user.name); printf("Age: %d \n", user.age); >int main(void) < person tom = ; print_person(tom); return 0; >

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

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

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

#include struct person < char* name; int age; >; void change_person(struct person * user) < user->age = user->age + 1; > int main(void) < struct person bob = ; printf("Before change. %s : %d \n", bob.name, bob.age); change_person(&bob); printf("After change. %s : %d \n", bob.name, bob.age); return 0; >

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

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

Before change. Bob : 22 After change. Bob : 23

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

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

#include struct person < char* name; int age; >; struct person create_person(char* name, int age) < struct person user; user.name = name; user.age = age; return user; >int main(void)

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

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

При передаче членов структур в функции фактически передается значение члена. Следовательно, передается обычная переменная. Рассмотрим для примера следующую структуру:
struct fred char x;
int y;
float z;
char s[10];
> mike;

Ниже приведены примеры передачи каждого члена в функцию:

func(mike.х); /* передача символьного значения х */
func2(mike.у); /* передача целочисленного значения у */
func3(mike.z); /* передача вещественного значения z */
func4(mike.s); /* передача адреса строки s */
func(mike.s[2]); /* передача символьного значения s [2] */

Тем не менее, если необходимо передать адрес отдельного члена структуры, следует поместить оператор & перед именем структуры. Например, для передачи адреса элементов структуры mike следует написать:

func(&mxke.x) ; /* передача адреса символа x */
func2(&mike.у); /* передача адреса целого у */
func3(&mike.z); /* передача адреса вещественного z */
func4(mike.s) ; /* передача адреса строки s */
func(&mike.s [2]); /* передача адреса символа s[2] */

Обратим внимание, что оператор & стоит перед именем структуры, а не перед именем члена. Помимо этого, массив s сам по себе является адресом, поэтому не требуется оператора &. Тем не менее, когда осуществляется доступ к отдельному символу строки s, как показано в последнем примере, оператор & необходим.

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

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

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

/* объявление типа структуры */
struct struct_type int a, b;
char ch;
>;

void f1(struct struct_type parm);

int main(void)
struct struct_type arg; /* объявление arg */
arg.a = 1000;
f1(arg);
return 0;
>

void f1(struct struct_type parm) printf(«%d», parm.a);
>

Данная программа выводит число 1000 на экран. Можно видеть, что как arg, так и parm объявлены как структуры типа struct_type.

C++. Структуры. Часть 4. Структуры и функции. Передача структуры в функцию в среде CLR. Возврат структуры из функции

Структуры. Часть 4. Структуры и функции. Передача структуры в функцию в среде CLR . Возврат структуры из функции

Поиск на других ресурсах:

1. Какие существуют способы передачи структуры в функцию?

Существует 2 способа передачи native -структуры в функцию в качестве параметра:

  • передача структуры по значению. При такой передаче делается копия структурной переменной в памяти. Если структура имеет большой размер, то такой способ неэффективен. Преимуществом этого способа есть то, что все манипуляции с копией структуры в функции не влияют на исходную переменную;
  • передача указателя на структуру. В этом случае передается только указатель на структуру а не вся структура. Если структура занимает большой объем памяти, то такой способ обеспечивает быструю передачу значений структурной переменной в функцию. Это связано с тем, что передается только указатель на структуру. Недостатком этого способа есть то, что в функции случайно можно изменить значения исходной структурной переменной, в тех случаях когда это нежелательно.
2. Какие есть способы возврата структуры из функции?

Так же, как и при передаче структуры в функцию (см. п.1), существуют 2 способа возврата:

  • возврат структуры по значению;
  • возврат указателя на структуру.

Преимущества и недостатки каждого способа такие же, как описано в п. 1.

3. Пример передачи native -структуры в функцию по значению

Пусть в модуле «MyStruct.h» даны объявления native -структуры:

// native-структура, которая описывает точку на координатной плоскости struct MyPoint < int x; int y; >;

Пусть в некотором классе объявляется функция EqualPoints() , которая сравнивает две точки на координатной плоскости. Функция возвращает true , если точки эквивалентны (равны между собой). В другом случае функция возвращает false .

// функция, которая сравнивает на равенство две точки public: bool EqualPoints(MyPoint p1, MyPoint p2) < bool f = false; if ((p1.x == p2.x) && (p1.y == p2.y)) f = true; return f; >

Тогда использование функции EqualPoints() может быть следующим:

// подключение модуля "MyStruct.h" #include "MyStruct.h" . // передача native-структуры в функцию по значению bool f_equal; MyPoint pt1, pt2; // p1, p2 – переменные типа "структура" // заполнение значениями pt1.x = 23; pt1.y = 35; pt2.x = 23; pt2.y = 35; f_equal = this->EqualPoints(pt1, pt2); // f_equal = true pt1.x = 100; f_equal = EqualPoints(pt1, pt2);
4. Пример передачи native -структуры в функцию по указателю

Пусть задана native -структура:

// native-структура struct MyPoint < int x; int y; >;

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

// передача указателя на структуру MyPoint bool EqualPointsP(MyPoint * p1, MyPoint * p2) < bool f = false; if ((p1->x == p2->x) && (p1->y == p2->y)) f = true; return f; >

Программный код, демонстрирующий использование функции EqualPoints() .

// Передача структуры по указателю MyPoint p1; MyPoint p2; bool f_equal; p1.x = 28; p1.y = 35; p2.x = 28; p2.y = 35; f_equal = EqualPointsP(&p1, &p2); // f_equal = true p2.y = 100; f_equal = EqualPointsP(&p1, &p2); // f_equal = false
5. Как передать в функцию managed -структуру, которая объявлена с квалификатором ref ? Пример

Пусть задана следующая ref -структура.

// ref-структура ref struct MyPointRef < int x; int y; >;

Структуры с квалификатором ref есть структурами ссылочного типа. Для таких структур память должна выделяться с помощью утилиты gcnew . Поэтому, в функцию можно передать только ссылку на такие структуры.

Пусть дана функция LengthRef() , которая определяет длину линии, которая соединяет 2 точки. Функция получает две ref -структуры в качестве параметров.

// Функция, определяющая длину между двумя точками float LengthRef(MyPointRef ^p1, MyPointRef ^p2) < float l; l = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return l; >

Использование функции LengthRef() в некотором программном коде.

// передача ref-структуры в функцию MyPointRef ^ pt1; MyPointRef ^ pt2; float len; // выделение памяти для ref-структур pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение ref-структур значениями pt1->x = 35; pt1->y = 35; pt2->x = 40; pt2->y = 40; len = LengthRef(pt1, pt2); // len = 7.071068
6. Как передать в функцию managed -структуру, которая объявлена с квалификатором value ? Пример

Managed -структуру, объявленную с квалификатором value можно передать в функцию одним из двух способов:

  • по значению;
  • по указателю.

Ниже приведены оба способа для value -структуры MyPointValue , которая имеет следующее объявление.

// value-структура value struct MyPointValue < int x; int y; >;

Способ 1.

Пусть задана функция LengthValue() , определяющая расстояние между двумя точками. Функция получает входным параметром две структуры типа MyPointValue . Структуры передаются как параметр-значение.

// определение расстояния между двумя точками float LengthValue(MyPointValue p1, MyPointValue p2) < float len; len = (float)Math::Sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); return len; >

Пример использования функции LengthValue() в другом программном коде.

// передача value-структуры по значению MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 35; pt1.y = 50; pt2.x = 40; pt2.y = 55; len = LengthValue(pt1, pt2); // len = 7.071068

Способ 2. Передача структуры по указателю.

Пусть задана функция LengthValue() , получающая два указателя на структуры типа MyPointValue .

// функция получает указатель на value-структуру float LengthValueP(MyPointValue *p1, MyPointValue *p2) < float len; len = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return len; >

Использование функции LengthValue() в программе.

// передача value-структуры по указателю MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 0; pt1.y = 0; pt2.x = 10; pt2.y = 10; len = LengthValueP(&pt1, &pt2); // len = 14.14214
7. Как реализовать возврат экземпляра native -структуры из функции? Пример

Возвратить native -структуру можно:

  • по значению;
  • по адресу.

Пусть задана структура MyPoint

// native-структура struct MyPoint < int x; int y; >;

Пусть в программе реализована функция GetCenterLine() , которая вычисляет координаты середины отрезка, соединяющего 2 точки. Функция получает 2 параметра – координаты концов отрезка.

// функция, возвращающая native-структуру // функция вычисляет координаты середины отрезка MyPoint GetCenterLine(MyPoint p1, MyPoint p2) < MyPoint res; res.x = (p1.x + p2.x)/2; res.y = (p1.y + p2.y)/2; return res; >

Демонстрация возврата native -структуры по значению.

MyPoint pt1; MyPoint pt2; MyPoint res; // результат, память уже выделена pt1.x = 30; pt1.y = 20; pt2.x = 36; pt2.y = 40; res = GetCenterLine(pt1, pt2); // res - координаты середины отрезка
8. Пример возврата из функции указателя на native -структуру

Пусть задана структура MyPoint

// native-структура struct MyPoint < int x; int y; >;

Пусть реализована функция GetCenterLine() , которая получает 2 точки и возвращает указатель на структуру. В теле функции реализовано выделение памяти для структуры оператором new .

MyPoint * GetCenterLine(MyPoint p1, MyPoint p2) < MyPoint * res; // указатель на структуру MyPoint // выделение памяти для структуры res = new MyPoint; // вычисление середины отрезка - заполнение значениями resP->x = (p1.x + p2.x)/2; resP->y = (p1.y + p2.y)/2; return res; >

Демонстрация работы с функцией GetCenterLine() .

// возвращение native-структуры по указателю MyPoint * resPt; // указатель на структуру – память для структуры еще не выделена MyPoint pt1, pt2; // экземпляры структуры pt1.x = 28; pt1.y = 40; pt2.x = 38; pt2.y = 50; // вызов функции GetCenterLine() // для указателя resPt память выделяется внутри функции resPt = GetCenterLine(pt1, pt2); // проверка int d; d = resPt->x; // d = 33 d = resPt->y; // d = 45
9. Как возвратить экземпляр value -структуры из функции?

Если в среде CLR описана структура с квалификатором value , то возврат экземпляра такой структуры из функции ничем не отличается от возвращения native -структуры (см. п. 7.).

10. Пример возврата указателя ( ^ ) на value -структуру

Если структура объявлена с квалификатором value , то функция может возвращать указатель на эту структуру. Допускается использование двух видов указателей:

  • классического указателя, который обозначается символом ‘*’ . Возврат такого указателя из функции не отличается от возврата указателя на native -структуру (см. п. 8);
  • указателя, предназначенного для работы с объектами среды CLR . Такой указатель обозначается символом ‘^‘ . Память для такого указателя выделяется утилитой gcnew . Ниже приведен пример возврата из функции такого указателя на value -структуру.

Пусть объявлена структура с квалификатором value

// value-структура value struct MyPointValue < int x; int y; >;

Пусть нужно реализовать функцию GetCenterLineVP() , которая получает 2 точки и возвращает указатель на результирующую value -структуру. Результирующая структура содержит координаты центра отрезка, который соединяет точки. Функция имеет следующий вид:

// функция возвращает указатель на value-структуру MyPointValue ^ GetCenterLineVP(MyPointValue p1, MyPointValue p2) < MyPointValue ^ pv; // указатель на структуру MyPointValue pv = gcnew MyPointValue; pv->x = (p1.x + p2.x)/2; pv->y = (p1.y + p2.y)/2; return pv; >

Демонстрация вызова функции из другого программного кода:

// создание экземпляров структур с инициализацией MyPointValue pt1 = < 20, 30 >; MyPointValue pt2 = < 40, 60 >; // указатель на структуру MyPointValue MyPointValue ^ resPt; // вызов функции GetCenterLineVP() // внутри функции выделяется память для структуры, // на которую указывает resPt resPt = GetCenterLineVP(pt1, pt2); // проверка int d; d = resPt->x; // d = 30 d = resPt->y; // d = 45
11. Пример возврата из функции структуры, которая объявлена с квалификатором ref

Для структуры, которая объявлена с квалификатором ref есть определенные особенности использования. Такая структура есть структурой ссылочного типа. Поэтому функция должна возвращать ссылку на такую структуру (указатель на структуру). Возвратить экземпляр ref -структуры (по значению) из функции не удастся (см. п. 5).

Пусть объявлена структура

// ref-структура ref struct MyPointRef < int x; int y; >;

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

// функция, возвращающая ref-структуру MyPointRef ^ GetCenterLineRef(MyPointRef ^p1, MyPointRef ^p2) < MyPointRef ^resPt; // выделение памяти для указателя resPt resPt = gcnew MyPointRef; // заполнение значениями полей указателя resPt->x = (p1->x + p2->x)/2; resPt->y = (p1->y + p2->y)/2; return resPt; >

Демонстрация использования функции в другом программном коде.

// указатели на ref-структуру MyPointRef ^pt1; MyPointRef ^pt2; MyPointRef ^resPt; // выделение памяти для указателей pt1, pt2 pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение значениями pt1->x = 20; pt1->y = 20; pt2->x = 30; pt2->y = 40; // вызов функции GetCenterLineRef() // память для указателя resPt выделяется внутри функции resPt = GetCenterLineRef(pt1, pt2); // проверка int d; d = resPt->x; // d = 25 d = resPt->y; // d = 30

Связанные темы

  • Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
  • Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native-структур
  • Структуры. Часть 3. Работа с managed-структурами в среде CLR. Квалификаторы ref и value. Объявление структурных переменных. Массивы managed-структурных переменных. Инициализация managed-структур
  • Функции. Часть 1. Описание функции. Фактические и формальные параметры. Передача параметров в функцию по значению и по адресу. Прототип функции
  • Функции. Часть 2. Функции и массивы. Передача одномерного и многомерного массива в функцию. Передача структуры и класса в функцию

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

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