В какой библиотеке c определяется функция struct. Структуры
Недавно познакомился со структурами C/C++ - struct. Господи, да «что же с ними знакомиться» скажете вы? Тем самым вы допустите сразу 2 ошибки: во-первых я не Господи, а во вторых я тоже думал что структуры - они и в Африке структуры. А вот как оказалось и - нет. Я расскажу о нескольких жизненно-важных подробностях, которые кого-нибудь из читателей избавят от часовой отладки…
Выравнивание полей в памяти
Обратите внимание на структуру:Struct Foo
{
char ch;
int value;
};
Ну во-первых какой у этой структуры размер в памяти? sizeof(Foo) ?
Размер этой структуры в памяти зависит от настроек компилятора и от директив в вашем коде…
В общем выравниваются в памяти поля по границе кратной своему же размеру. То есть 1-байтовые поля не выравниваются, 2-байтовые - выравниваются на чётные позиции, 4-байтовые - на позиции кратные четырём и т.д. В большинстве случаев (или просто предположим что сегодня это так) выравнивание размера структуры в памяти составляет 4 байта. Таким образом, sizeof(Foo) == 8 . Где и как прилепятся лишние 3 байта? Если вы не знаете - ни за что не угадаете…
- 1 байт: ch
- 2 байт: пусто
- 3 байт: пусто
- 4 байт: пусто
- 5 байт: value
- 6 байт: value
- 7 байт: value
- 8 байт: value
Struct Foo
{
char ch;
short id;
int value;
};
Оно выглядит вот так:
- 1 байт: ch
- 2 байт: пусто
- 3 байт: id
- 4 байт: id
- 5 байт: value
- 6 байт: value
- 7 байт: value
- 8 байт: value
Struct Foo
{
char ch;
short id;
short opt;
int value;
};
Посмотрим на размещение полей в памяти:
- 1 байт: ch
- 2 байт: пусто
- 3 байт: id
- 4 байт: id
- 5 байт: opt
- 6 байт: opt
- 7 байт: пусто
- 8 байт: пусто
- 9 байт: value
- 10 байт: value
- 11 байт: value
- 12 байт: value
#pragma pack(push, 1)
struct Foo
{
// ...
};
#pragma pack(pop)
Мы установили размер выравнивания в 1 байт, описали структуру и вернули предыдущую настройку. Возвращать предыдущую настройку - категорически рекомендую. Иначе всё может закончиться очень плачевно. У меня один раз такое было - падало Qt. Где-то заинклюдил их.h-ник ниже своего.h-ника…
Битовые поля
В комментариях мне указали на то, что битовые поля в структурах по стандарту являются «implementation defined» - потому их использования лучше избежать, но для меня соблазн слишком велик...Мне становится не то что неспокойно на душе, а вообще становится хреново, когда я вижу в коде заполнение битовых полей при помощи масок и сдвигов, например так:
Unsigned field = 0x00530000;
// ...
field &= 0xFFFF00FF;
field |= (id) << 8;
// ...
field &= 0xFFFFFF83;
field |= (proto) << 2;
Всё это пахнет такой печалью и такими ошибками и их отладкой, что у меня сразу же начинается мигрень! И тут из-за кулис выходят они - Битовые Поля. Что самое удивительное - были они ещё в языке C, но кого ни спрашиваю - все в первый раз о них слышат. Этот беспредел надо исправлять. Теперь буду давать им всем ссылку, ну или хотя бы ссылку на эту статью.
Как вам такой кусок кода:
#pragma pack(push,1)
struct IpHeader
{
uint8_t header_length:4;
uint8_t version:4;
uint8_t type_of_service;
uint16_t total_length;
uint16_t identificator;
// Flags
uint8_t _reserved:1;
uint8_t dont_fragment:1;
uint8_t more_fragments:1;
uint8_t fragment_offset_part1:5;
uint8_t fragment_offset_part2;
uint8_t time_to_live;
uint8_t protocol;
uint16_t checksum;
// ...
};
#pragma pack(pop)
А дальше в коде мы можем работать с полями как и всегда работаем с полями в C/C++. Всю работу по сдвигам и т.д. берет на себя компилятор. Конечно же есть некоторые ограничения… Когда вы перечисляете несколько битовых полей подряд, относящихся к одному физическому полю (я имею ввиду тип который стоит слева от имени битового поля) - указывайте имена для всех битов до конца поля, иначе доступа к этим битам у вас не будет, иными словами кодом:
#pragma pack(push,1)
stuct MyBitStruct
{
uint16_t a:4;
uint16_t b:4;
uint16_t c;
};
#pragma pack(pop)
Получилась структура на 4 байта! Две половины первого байта - это поля a и b . Второй байт не доступен по имени и последние 2 байта доступны по имени c . Это очень опасный момент. После того как описали структуру с битовыми полями обязательно проверьте её sizeof !
Также порядок размещения битовых болей в байте зависит от порядка байтов. При порядке LITTLE_ENDIAN битовые поля раздаются начиная со первых байтов, при BIG_ENDIAN - наоборот…
Порядок байтов
Меня также печалят в коде вызовы функций htons() , ntohs() , htonl() , nthol() в коде на C++. На C это ещё допустимо, но не на С++. С этим я никогда не смирюсь! Внимание всё нижесказанное относится к C++!Ну тут я буду краток. Я в одной из своих предыдущих статей уже писал что нужно делать с порядками байтов. Есть возможность описать структуры, которые внешне работают как числа, а внутри сами определяют порядок хранения в байтах. Таким образом наша структура IP-заголовка будет выглядеть так:
#pragma pack(push,1)
struct IpHeader
{
uint8_t header_length:4;
uint8_t version:4;
uint8_t type_of_service;
u16be total_length;
u16be identificator;
// Flags
uint8_t _reserved:1;
uint8_t dont_fragment:1;
uint8_t more_fragments:1;
uint8_t fragment_offset_part1:5;
uint8_t fragment_offset_part2;
uint8_t time_to_live;
uint8_t protocol;
u16be checksum;
// ...
};
#pragma pack(pop)
Внимание собственно обращать на типы 2-байтовых полей - u16be . Теперь поля структуры не нуждаются ни в каких преобразованиях порядка байт. Остаются проблемы с fragment_offset , ну а у кого их нет - проблем-то. Тем не менее тоже можно придумать шаблон, прячущий это безобразие, один раз его оттестировать и смело использовать во всём своём коде.
«Язык С++ достаточно сложен, чтобы позволить нам писать на нём просто» Как ни странно - Я
З.Ы. Планирую в одной из следующих статей выложить идеальные, с моей точки зрения, структуры для работы с заголовками протоколов стека TCP/IP. Отговорите - пока не поздно!
Перед тем как приступить к изучению классов в C++, мы рассмотрим тип данных подобный классу — структуры. Структуры полезны, когда нам надо объединить несколько переменных с разными типами под одним именем. Это делает программу более компактной и более гибкой для внесения изменений. Также структуры незаменимы, когда необходимо сгруппировать некоторые данные, например, запись из базы данных или контакт из книги адресов. В последнем случае структура будет содержать такие данные контакта как имя, адрес, телефон и т.п.
Синтаксис
В процессе написания программы может потребоваться сгруппировать разные данные. Например, вы захотите хранить координаты некоторых объектов и их имена. Вы можете сделать это с помощью :
Int x_coor; int y_coor; string names;
Но так как каждый элемент одного массива связан с другим, то при изменении одного, придется менять остальные тоже. И чем больше данных вам надо объединить, тем сложнее будем такая программа. Поэтому для объединения разных данных используются структуры .
Формат объявления структуры выглядит так:
Struct Car { int x_coor; int y_coor; string name; };
Объявляя структуру, мы вводим в программу наш собственный тип данных, которым можем пользоваться, так же как и стандартными типами, т.е. объявление переменной нашего типа будет таким:
StructName variableName;
structName — имя структуры, variableName — имя переменной.
x_coor, y_coor и name — поля нашей структуры. При объявлении структуры мы создаем составной тип данных, с помощью которого можно создавать переменные, которые сочетают в себе несколько значений (например, координаты и имя). Внутри структуры каждому полю мы даем имя, чтобы потом обращаться к этому значению по его имени.
Для доступа к полям структуры используется точка:
// объявляем переменную Car myCar; // и используем её myCar.x_coor = 40; myCar.y_coor = 40; myCar.name = "Porche";
Как видите, вы можете хранить в структуре столько полей, сколько вам угодно и они могут иметь разные типы.
Рассмотрим пример, демонстрирующий сочетание массивов и структур.
#include
Так же как и с простыми типами (int, например), вы можете создавать массивы структур. А с каждым элементом этого массива работать так же как и с отдельной переменной. Для доступа к полю name первого элемента массива структур, просто напишите:
Players[ 0 ].name
Структуры и функции
Очень часто требуется писать функции, которые принимают структуры в качестве аргумента или возвращают структуру. Например, если вам надо написать небольшую космическую аркаду, вам может понадобится функция для инициализации нового противника:
Struct EnemySpaceShip { int x_coordinate; int y_coordinate; int weapon_power; }; EnemySpaceShip getNewEnemy();
Функция getNewEnemy должна возвращать структуру с инициализированными полями:
EnemySpaceShip getNewEnemy () { EnemySpaceShip ship; ship.x_coordinate = 0; ship.y_coordinate = 0; ship.weapon_power = 20; return ship; }
На самом деле эта функция вернет копию созданной локальной переменной ship. Это значит, что каждое поле структуры будет скопировано в новую переменную. В нашем случае копирование малого количества полей не заметно, но когда вы работаете с большими объемами данных нужно избегать лишних действий, подробнее об этом поговорим в статье про указатели.
Таким образом, для получения новой переменной будем использовать следующий код:
EnemySpaceShip ship = getNewEnemy();
Теперь эту переменную можно использовать как обычную структуру.
Передавать структуры в функцию можно так:
EnemySpaceShip upgradeWeapons (EnemySpaceShip ship) { ship.weapon_power += 10; return ship; }
Когда мы передаем структуру в функцию, она копируется, так же как и при возвращении структуры. Поэтому любые изменения сделанные внутри функции будут потеряны, поэтому мы возвращаем структуру после изменения.
Использование функции:
Ship = upgradeWeapons(ship);
Когда вызывается функция, переменная ship копируется и изменяется в функции, а когда переменная возвращается, она снова копируется и перезаписывает поля оргинальной переменной.
И наконец, программа для создания и улучшения одного корабля:
Struct EnemySpaceShip { int x_coordinate; int y_coordinate; int weapon_power; }; EnemySpaceShip getNewEnemy() { EnemySpaceShip ship; ship.x_coordinate = 0; ship.y_coordinate = 0; ship.weapon_power = 20; return ship; } EnemySpaceShip upgradeWeapons(EnemySpaceShip ship) { ship.weapon_power += 10; return ship; } int main() { EnemySpaceShip enemy = getNewEnemy(); enemy = upgradeWeapons(enemy); }
Указатели
Если вы работаете с на структуру, то для доступа к переменным надо использовать оператор «->» вместо точки. Все свойства указателей не изменяются. Пример:
#include
Тип переменной определяет: её размер в памяти, тип данных, которые она может хранить и операции, которые можно производить с этой переменной.
Тип данных является категорией. В языке С++ программист может создать любой тип данных на основе базовых типов. Новые типы данных необходимо создавать для решения конкретных практических задач. Например: реализация работы деканата.
Успех программы часто зависит от удачного выбора способа представления данных. С помощью структур возможно моделировать сложные объекты, возникающие при решении задач. Структуры представляют средство для доступа к записям, которые содержат поля одного или нескольких типов.
Для использования структуры необходимо:
1. установить шаблон для структуры
2. объявить переменную, соответствующую этому шаблону
3. осуществить доступ к компонентам структуры.
Шаблон структуры
Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник:
struct sprav {
char fio;
long num;
};
Данный шаблон описывает структуру с именем типа структуры sprav, состоящую из двух компонентов: строки fio и целой переменной num типа long. Имя типа структуры sprav необязательно и используется для ссылки на эту структуру. Компоненты структуры - данные любого типа, включая и другие структуры. Имя внутри структуры может быть таким же, как имя объекта вне структуры. Если шаблон описан внутри функции - он доступен только этой функции, если шаблон описан вне функции - он доступен любой функции программы. Установка шаблона не вызывает никаких действий в программе.
Структурные переменные
Объявление структурных переменных приводит к выделению памяти для компонент структуры, куда можно записать данные или откуда можно прочитать их. Для объявления структурных переменных имеются несколько способов.
1. Установить структурный шаблон:
struct sprav {
char fio;
long num;
};
Объявить простую переменную, массив структур, указатель на структуру: struct sprav tel1, tel2, *tel3;
2. Установить структурный шаблон с помощью макроопределения:
#define SPRAV struct sprav
SPRAV {
char fio;
long num;
};
Объявить переменные:
SPRAV sp1, sp2, *sp3;
3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь):
struct {
char fio;
long num;
} tel1, tel2, *tel3;
4. Ввести новый тип данных (TEL)-структура определенного вида:
typedef struct {
char fio;
long num;
} TEL;
Объявить переменные нового типа:
TEL tel1, tel2, *tel3;
Если программа достаточно объемна, представляется более удобным четвертый способ.
Инициализация структуры
Инициализировать можно только внешние или статические структуры.
static struct {
char fio;
long num;
} tel={
"Иванов Ф.А.", 456756,
"Петров В.П.", 632345
};
Доступ к компонентам структуры
Доступ к компонентам структуры продемонстрируем с помощью примеров.
/* Обращение к элементам структуры через имя переменной */
#include
#include
void main(void)
{
struct{
char fio; /* фамилия */
long num; /* телефон */
} tel1, tel2;
puts("введите фио абонента-");
gets(tel1.fio);
puts("введите его номер-");
scanf("%ld",&tel1.num);
tel2=tel1; /* нельзя так же сравнивать структуры */
puts("Введено:");
printf("Фамилия:%s номер: %ld\n",tel2.fio,tel2.num);
}
/* Динамическое выделение памяти для структуры */
#include
#include
#include
struct sprav {
char fio;
long num;
};
void main(void)
{
struct sprav *tel1, *tel2;
clrscr();
/* Выделение памяти для структуры */
tel1=(struct sprav *)malloc(sizeof(struct sprav));
tel2=(struct sprav *)malloc(sizeof(struct sprav));
gets(tel1->fio);
puts("введите его номер-");
scanf("%ld",&tel1->num);
*tel2= *tel1;
puts("Введено:");
printf("Фамилия:%s номер: %ld\n",(*tel2).fio,(*tel2).num);
}
Массив структур
/* Массив структур. Обращение к элементам структуры через */
/* имя элемента массива */
#include
#include
#include
#define SPRAV struct sprav
void main(void)
{
SPRAV{
char fio;
long num;
};
SPRAV tel; /* массив структур - 5 элементов */
char fio_tek;
int i;
clrscr();
/* ввод данных в массив структур */
for(i=0; i<5; i++)
{
puts("введите фио абонента-");
gets(tel[i].fio);
puts("введите его номер-");
scanf("%ld",&tel[i].num);
getchar();
}
gets(fio_tek);
/* поиск структуры по фамилии абонента */
for(i=0; i<5; i++)
if(!strcmp(fio_tek,tel[i].fio)) break;
if(i!=5) /* цикл закончен по break */
tel[i].num);
else /* цикл выполнился полностью */
puts("Абонент не найден");
}
/* Массив структур. Память выделяется динамически. */
/* Обращение к элементам структуры через указатель */
#include
#include
#include
#include
typedef struct{
char fio;
long num;
} TEL;
void main(void)
{
TEL *tel;
char fio_tek;
int i;
clrscr();
/* Выделение памяти для массива - 3 элемента */
tel=(TEL *)malloc(sizeof(TEL)*3);
for(i=0; i<3; i++)
{
puts("введите фио абонента-");
gets((tel+i)->fio);
puts("введите его номер-");
scanf("%ld",&(tel+i)->num);
getchar();
}
puts("Выбор телефона по фамилии");
gets(fio_tek);
for(i=0; i<5; i++,tel++)
if(!strcmp(fio_tek,tel->fio)) break;
if(i!=5)
printf("номер абонента %s равен %ld\n",fio_tek, \
tel->num);
else
puts("Абонент не найден");
}
Передача структуры в функцию
Непосредственный доступ к компонентам структуры - плохой стиль программирования. Все операции, которые разрешены применительно к структуре, должны быть при этом реализованы в виде отдельных функций. Не все компиляторы языка Си позволяют передавать структуры в функцию по значению, поэтому в примерах передача структуры идет через указатель.
/* Передача структуры в функцию через указатель на структуру */
/* Определение комплексного числа через структуру и действия */
/* над комплексными числами (ввод, вывод, вычисление суммы) */
#include
typedef struct { float a; /* действительная часть */
float b; /* мнимая часть */
} COMPLEX;
void vvod(COMPLEX *,float,float);
void sum(COMPLEX *,COMPLEX *,COMPLEX *);
void out(COMPLEX *);
void main(void)
{
COMPLEX x,y,z;
vvod(&x,2.5,6.7);
vvod(&y,6.89,8.45);
puts("Введены числа:");
out(&x);
out(&y);
sum(&x,&y,&z);
puts("Сумма комплексных чисел равна:");
out(&z);
}
/* Вывод комплексного числа */
void out(COMPLEX *p)
{
printf("(%.2f,%.2f)\n", (*p).a,(*p).b);
return;
}
/* Вычисление суммы двух комплексных чисел */
void sum(COMPLEX *p1,COMPLEX *p2,COMPLEX *p3)
{
(*p3).a=(*p1).a+(*p2).a;
(*p3).b=(*p1).b+(*p2).b;
return;
}
/* Ввод значений для элементов структуры */
void vvod(COMPLEX *p,float a, float b)
{
p->a=a;
p->b=b;
return;
}
Вложенные структуры
Структура, являющаяся компонентом другой структуры, называется вложенной.
/* Даны четыре точки - центры четырех окружностей. Заполнить структуру окружность, если все окружности проходят через начало координат. */
#include
#include
#include
#include
struct POINT {
float x;
float y;
};
struct CIRCLE {
struct POINT point; /* вложенная структура */
double r;
} circle, *p;
void main (void)
{
int i,j;
float a,b,c,d;
clrscr();
gotoxy(17,1);
cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК:\r\n");
for(i=0;i<2;i++)
{
cprintf ("\n\n ВВЕДИТЕ X: ");
cprintf ("X[%d]= ",i+1);
cscanf("%f",&circle[i].point.x);
cprintf ("\n ВВЕДИТЕ Y: ");
cprintf ("Y[%d]= ",i+1);
cscanf ("%f",&circle[i].point.y);
}
p=circle;
gotoxy(17,12);
cputs("РЕЗУЛЬТАТ:\r\n\n");
for(i=0;i<2;i++)
{
a=p->point.x;
b=p->point.y;
c=sqrt(a*a+b*b);
p->r=c;
cprintf("\nРАДИУС: %lf ЦЕНТР (%f,%f)\r\n",p->r,a,b);
p++;
}
Последнее обновление: 09.10.2017
Ранее для определения классов мы использовали ключевое слово class . Однако C++ предоставляет еще один способ для определения пользовательских типов, который заключается в использовании структур. Данный способ был унаследован языком С++ еще от языка Си.
Структура в языке C++ представляет собой производный тип данных, который представляет какую-то определенную сущность, также как и класс. Нередко структуры применителько к С++ также называют классами. И в реальности различия между ними не такие большие.
Для определения структуры применяется ключевое слово struct , а сам формат определения выглядит следующим образом:
Struct имя_структуры { компоненты_структуры };
Имя_структуры представляет произвольный идентификатор, к которому применяются те же правила, что и при наименовании переменных.
После имени структуры в фигурных скобках помещаются Компоненты_структуры , которые представляют набор описаний объектов и функций, которые составляют структуру.
Например, определим простейшую структуру:
#include
Здесь определена структура person , которая имеет два элемента: age (представляет тип int) и name (представляет тип string).
После определения структуры мы можем ее использовать. Для начала мы можем определить объект структуры - по сути обычную переменную, которая будет представлять выше созданный тип. Также после создания переменной структуры можно обращаться к ее элементам - получать их значения или, наоборот, присваивать им новые значения. Для обращения к элементам структуры используется операция "точка":
Имя_переменной_структуры.имя_элемента
По сути структура похожа на класс, то есть с помощью структур также можно определять сущности для использования в программе. В то же время все члены структуры, для которых не используется спецификатор доступа (public, private), по умолчанию являются открытыми (public). Тогда как в классе все его члены, для которых не указан спецификатор доступа, являются закрытыми (private).
Кроме того мы можем инициализировать структуру, присвоив ее переменным значения с помощью синтаксиса инициализации:
Person tom = { 34, "Tom" };
Инициализация структур аналогична инициализации массивов: в фигурных скобках передаются значения для элементов структуры по порядку. Так как в структуре person первым определено свойство, которое представляет тип int - число, то в фигурных скобках вначале идет число. И так далее для всех элементов структуры по порядку.
При этом любой класс мы можем представить в виде структуры и наоборот. Возьмем, к примеру, следующий класс:
Class Person { public: Person(std::string n, int a) { name = n; age = a; } void move() { std::cout << name << " is moving" << std::endl; } void setAge(int a) { if (a > 0 && a < 100) age = a; } std::string getName() { return name; } int getAge() { return age; } private: std::string name; int age; };
Данный класс определяет сущность человека и содержит ряд приватных и публичных переменных и функции. Вместо класса для определения той же сущности мы могли бы использовать структуру:
#include
И в плане конечного результата программы мы не увидели бы никакой разницы.
Когда использовать структуры? Как правило, структуры используются для описания таких данных, которые имеют только набор публичных атрибутов - открытых переменных. Например, как та же структура person, которая была определена в начале статьи. Иногда подобные сущности еще называют аггрегатными классами (aggregate classes).
А теперь только представьте — вы сами можете создавать, своего рода, типы данных, которые вам необходимы и с которыми вам будет удобно работать! И это несложно!
Структура — это, некое объединение различных переменных (даже с разными типами данных), которому можно присвоить имя. Например можно объединить данные об объекте Дом: город (в котором дом находится), улица, количество квартир, интернет(проведен или нет) и т.д. в одной структуре. В общем, можно собрать в одну совокупность данные обо всем, что угодно, точнее обо всем, что необходимо конкретному программисту. Всем сразу стало понятно:)
Если вы только приступаете к знакомству со структурами в С++, сначала, вам необходимо ознакомиться с синтаксисом структур в языке С++ . Рассмотрим простой пример, который поможет познакомиться со структурами и покажет, как с ними работать. В этой программе мы создадим структуру, создадим объект структуры, заполним значениями элементы структуры (данные об объекте) и выведем эти значения на экран. Ну что же, приступим!
#include
В строках 4 — 10 мы создаем структуру. Чтобы ее объявить используем зарезервированное слово struct и даем ей любое, желательно логичное, имя. В нашем случае — building . С правилами именования переменных, вы можете ознакомиться в этой статье . Далее открываем фигурную скобку { , перечисляем 4 элемента структуры через точку с запятой; , закрываем фигурную скобку } и в завершении ставим точку с запятой; . Это будет нашим шаблоном (формой) структуры.
В строке 16 объявляем объект структуры. Как и для обычных переменных, необходимо объявить тип данных. В этом качестве выступит имя нашей созданной структуры — building .
Как же заполнить данными (инициализировать) элементы структуры? Синтаксис таков: Имя объекта далее оператор точка. и имя элемента структуры. Например: apartment1.owner . Таким образом, в строках 18-21 присваиваем данные элементам структуры.
И так, данные мы внесли. Следующий вопрос: «Как к ним обратиться, как работать и использовать их в программе?» Ответ — «Очень просто — так же, как и при инициализации, используя точку. и имя элемента структуры». В строках 23 — 26 выводим заполненные элементы структуры на экран.
И вот что мы увидим в результате, когда скомпилируем нашу программу:
Владелец квартиры: Денис Квартира находится в городе: Симферополь Количество комнат: 5 Стоимость: 150000 $
Что ещё важно знать:
- Объект структуры можно объявить до функции main() . Это выглядело бы так:
- Инициализировать структуру можно и таким способом:
но так делают крайне редко;
- Структуру можно вкладывать в другие структуры (это мы рассмотрим в следующем примере).
Дополним предыдущий пример, чтобы увидеть дополнительные возможности работы со структурами.
Пример:
#include
Коментарии по коду программы:
Строка 17 — создание объекта built типа date в определении структуры building . Строки 42 — 43 : создаем указатель на структуру struct building *pApartment; и далее присваиваем ему адрес уже созданного и заполненного данными объекта pApartment = &apartment1; . Обращаясь к элементам структуры через указатель мы используем оператор -> (тире и знак >) . Это видно в строках 47 — 51.
В строке 62 показано, как можно инициализировать структуру. А именно, можно создать новый объект структуры и присвоить ему одним целым, уже созданный и заполненный данными, объект. В функцию show() передаем объект структуры, как параметр — строка 64. Результат:
Владелец квартиры: Денис
Квартира находится в городе: Симферополь
Количество комнат: 5
Стоимость: 150000 $
Дата постройки: январь 2013
Владелец квартиры: Игорь
Квартира находится в городе: Киев
Количество комнат: 4
Стоимость: 300000 $
Дата постройки: январь 2012
Для продолжения нажмите любую клавишу. . .
Разобрав этот пример, мы увидели на практике следующее:
- структуру можно вкладывать в другую структуру;
- увидели, как создаётся указатель на структуру;
- как нужно обращаться к элементу структуры через указатель. А именно, используя оператор -> ; В примере это было так: apartment0->owner , но можно и так (*apartment0).owner . Круглые скобки, во втором случае, обязательны.
- данные одной структуры можно присвоить другой структуре;
- можно структуру передать в функцию, как параметр (кстати, элементы структуры так же можно передавать в функцию, как параметры).
В дополнение ко всему, следует отметить, что функции могут так же возвращать структуры в результате своей работы. Например:
Building Set() { building object; // формирование объекта //... код функции return object; }
Вот так, вкратце, мы познакомились со структурами в языке С++, попрактиковались на примерах и узнали основы. Это только начало!