Структуры - это объединенная в единое целое множество компонентов данных.
В отличие от массива, всегда состоящего из однотипных элементов, компоненты структуры могут быть разных типов и все должны иметь различные имена. Например:
//Структура, описывающая товары на складе.
struct goods {
char* name; //наименование
long price;
float percent; //наименование в %
int voL;
char date[9]; //дата поставки
};
Комментарий:struct - спецификатор структурного типа, служебное слово goods - имя структурного типа(тег).
В фигурных скобках размещаются описания элементов, которые входят в каждый объект типа goods, ';' обязательна.
Есть и другие способы определения структур:
=typedef struct
=#define goods struct
=struct - направленная структура безъимянного типа.
struct
{
char processor[10];
int frequency;
int memory;
int disk;
} PIV_asus,Nvidia,Compaq;
Комментарий: введены три структуры(три обьекта) с именами PIV_asus,Nvidia,Compaq в каждую из которых входят элементы, в которые можно будет занести сведения о характеристиках конкретных ПК.
Определение структурного типа не связано с выделением памяти, а при каждом определении структуры(объекта), ей выделяется память в таком количестве, чтобы могли разместиться данные всех элементов.
! влиять на размещение структур можно с помощью процессорной директивы #pragma (выравнивание данных).
Инициализация структур похожа на инициализацию массивов.Непосредственно в определении конкретной структуры после ее имени и знак = в фигурных скобках размещается список начальных значений элементов.
struct goods coat={"пиджак черный",400000,7.5,200,"12.06.01"};
! в отличие от массивов допускается присваивание структур присваивание структур следующим образом: tea=coat;
С помощью уточненых имен:
имя_структуры.имя_элемента coat.name - указатель типа char* на строку "пиджак черный" coat.price - переменная типа long 400000
Перед точкой стоит не название структурного типа, а имя конкретной структуры, для которой ее определение выделила память.
Вектор есть совокупность элементов одного типа; struct является совокупностью элементов (практически) произвольных типов. Например:
struct address { // почтовый адрес
char* name; // имя "Jim Dandy"
long number; // номер дома 61
char* street; // улица "South Street"
char* town; // город "New Providence"
char* state[2]; // штат 'N' 'J'
int zip; // индекс 7974
}
определяет новый тип, названный address (почтовый адрес), состоящий из пунктов, требующихся для того, чтобы послать кому-нибудь корреспонденцию (вообще говоря, address не является достаточным для работы с полным почтовым адресом, но в качестве примера достаточен). Обратите внимание на точку с запятой в конце; это одно из очень немногих мест в C++, где необходимо ставить точку с запятой после фигурной скобки, поэтому люди склонны забывать об этом.
Переменные типа address могут описываться точно также, как другие переменные, а доступ к отдельным членам получается с помощью операции . (точка). Например:
address jd; jd.name = "Jim Dandy"; jd.number = 61;
Запись, которая использовалась для инициализации векторов, можно применять и к переменным структурных типов. Например:
address jd = {
"Jim Dandy",
61, "South Street",
"New Providence", {'N','J'}, 7974
};
Однако обычно лучше использовать конструктор . Заметьте, что нельзя было бы инициализировать jd.state строкой "NJ". Строки
оканчиваются символом '\0' ,
поэтому в "NJ" три символа, то есть на
один больше, чем влезет в jd.state.
К структурным объектам часто обращаются посредством указателей
используя операцию ->. Например:
void print_addr(address* p)
{
cout << p->name << "\n"
<< p->number << " " << p->street << "\n"
<< p->town << "\n"
<< chr(p->state[0]) << chr(p->state[1])
<< " " << p->zip << "\n";
}
Объекты типа структур можно присваивать, передавать как параметры функции и возвращать из функции в качестве результата. Например:
address current;
address set_current(address next)
{
address prev = current;
current = next;
return prev;
}
Остальные осмысленные операции, такие как сравнение (== и !=) не определены. Однако пользователь может определить эти операции; Размер объекта структурного типа нельзя вычислить просто как сумму его членов. Причина этого состоит в том, что многие машины требуют, чтобы объекты определенных типов выравнивались в памяти только по некоторым зависящим от архитектуры границам (типичный пример: целое должно быть выравнено по границе слова) или просто гораздо более эффективно обрабатывают такие объекты, если они выравнены в машине. Это приводит к "дырам" в структуре. Например, (на моей машине) sizeof (address) равен 24, а не 22, как можно было ожидать.
Заметьте, что имя типа становится доступным сразу после того, как оно встретилось, а не только после того, как полностью просмотрено все описание. Например:
struct link{
link* previous;
link* successor;
}
Новые объекты структурного типа не могут быть описываться, пока все описание не просмотрено, поэтому
struct no_good {
no_good member;
};
является ошибочным (компилятор не может установить размер no_good). Чтобы дать возможность двум (или более) структурным типам ссылаться друг на друга, можно просто описать имя как имя структурного типа. Например:
struct list; // должна быть определена позднее
struct link {
link* pre;
link* suc;
link* member_of;
};
struct list {
link* head;
}
Без первого описания list описание link вызвало бы к синтаксическую ошибку.