Операции над структурными переменными
Вложенные структуры
Инициализация структурных переменных
Разрешается выполнять инициализацию полей структурной переменной при её определении. Например:
struct Book {char name[20]; //определение шаблона структуры
char title[44];
int year;
float price;
};
Book // инициализация структурных переменных при их определении
first_book = {"Mitchel M.",
"Unesennie vetrom",
2007,
20000 },
child_book = {"Troepolskij G.",
"Belij Bim Chernoe Ucho",
2006,
10000 },
dog_book = {…..};
Инициализирующие значения располагаются в порядке объявления полей в структурном типе. Типы инициализирующих значений должны быть совместимы с типами соответствующих полей в определении структурного типа.
Поле, являющееся структурой, называют вложенной структурой. Естественно, что шаблон вкладываемой структуры должен быть уже известен компилятору. Например:
struct UDC {char class, subclass; int number;};
struct Book { struct UDC udc_class;
char name [20];
char title[44];
int year;
float price;
} first_book, child_book, dog_book;
Ссылка на поле вложенной структуры формируется из имени структурной переменной, имени структурного поля и имени вложенной структуры. Перечисленные имена разделяются символом «точка». Например:
first_book.udc_class.class= ‘A’; //(first_book.udc_class).class.
dog_book.udc_class.number= 681;
child_book.udc_class.class= 65; //объяснить, почему верно
Теоретически не существует ограничения на величину уровня вложенности структур.
Пусть имеем вложенные структуры:
struct Distance //длина в километрах и метрах
{ int km, m;
};
struct Pole //размеры прямоугольного поля
{Distance length;
Distance width,
};
Тогда инициализация структурной переменной типа Pole выглядит так:
Pole pole = { {2, 20}, {1, 5}};
Поля структурной переменной могут использоваться в выражениях и операторахв контексте их типа,в том числе и операторах ввода-вывода.Так же, как и для обычных операндов, действуют правила преобразования типов при смешивании операндов-полей разных типов. Например:
if (strcmp(first_book.name, "Mitchel M.") == 0) …… ;
if(first_book.year % 4==0) …… ;
first_book.name[0] = tolower(first_book.name[0]);
strcpy (first_book. name, "Mitchel M."); //поле-строка получает значение !!!!!
strcpy (first_book. title, "Unesennie vetrom");
cin >> child_book.title; //поле- строка получает значение !!!!!
first_book. year = 2007;
cin >> first_book. price;
Определить адрес структурной переменной или ее поля можно обычной операцией взятия адреса.
Непосредственно сравнивать две структурные переменные (даже одного типа) нельзя. Сравнивать можно только члены структур. Например:
struct { int a;
int b;
} v1, v2;
if ((v1.a == v2.a) && (v1.b == v2.b)) cout << “переменные равны”;
К структурным переменным, определенным с помощью одного и того же шаблона, применим оператор присваивания.!!! После его выполнения значения полей структурных переменных будут равны. Например:
first_book = child_book;
first_book = child_book = dog_book;
#include <windows.h>
RECT r1, r2 = { 2, 6, 4, 2 }, r3;
r1.left = 1;
r1.top = 5;
r1.right = 3;
r1.bottom = 1;
r3 = r1;
cout<< r3.left << endl;
При присваивании, байты памяти,выделенныеправой структурной переменной, копируются в память, выделенную компилятором для структурной переменной этого же типа, стоящей слева. Это так называемое поверхностное копирование.
НО!!! Поверхностное копирование полей-указателей может стать источником ошибок в дальнейшей работе.Если в структуре есть поля-указатели, то после присваивания будет существовать больше одной структурной переменной, поля которой указывают на одну и ту же область памяти.!!!
Если два структурных типа «закольцованы» (поля одного структурного типа объявляются через другой структурный тип и наоборот):
structA { B *pb;};
structB { A *pa;};
то допустимо использовать предварительное неполное определение любого из типов:
structB; // предварительное неполное определение типа B;
structA { B *pb;};
structB { A *pa;};
В данном случае предварительное неполное определение структурного типа B допустимо использовать в определении структурного типа A, так как определение указателя pb на структуру типа B не требует сведений о размере структуры типа B.
При обращении к элементам структуры с помощью указателя нужно учитывать приоритет операций. Для изменения порядка действий необходимо использовать явные скобки.
Выражение (*ptr_date).year представляет собой обращение к элементу year структуры, связанной с указателем ptr_date. Нельзя опускать скобки в этом выражении, так как приоритет операции точка (.) выше, чем операции доступ по указателю (*).
Для вложенных структур доступ к полям структурной переменной через указатель реализуется следующим образом: p->q->mem, что равносильно (p->q) -> mem (поскольку операции -> и . выполняются слева направо). Аналогично, выражение
stud. birthdate. month означает (stud. birthdate). month.