Шаг 82.
Описание структур

    На этом шаге мы начнем знакомиться со структурами.

    Структура - это множество, состоящее из одного или более объектов, возможно имеющих различные типы, объединенных под одним именем.

    Тип данных struct - один из основных строительных блоков данных в языке. Он предоставляет удобный способ объединения различных элементов, связанных между собой.

    Основные сведения о структурах рассмотрим на примере (комментарии расположены после примера).


    Пример. Иллюстрация использования структур.
#include <iostream.h>
struct date
{
       int day; 
       int month; 
       int year;
       int yearday; 
      char mon_name[5];
};
static int day_tab[2][13]=
    {0,31,28,31,30,31,30,31,31,30,31,30,31,
     0,31,29,31,30,31,30,31,31,30,31,30,31};
date d = { 0,0,1776,186,"июл" }; // d = { 4,7,1776,186,"июл" } 
date f = { 1,9,1986,0,"сент" };
void main() // Применение структур.
{
  void day_of_year(date *);
  void month_day(date *);
  date *p;
  month_day (&d);
  cout << "Работа функции month_day():\n";
  cout << d.yearday << "-му дню " << d.year 
    << " года соответствует дата: "<< d.day << " " << d.month << endl;
  day_of_year (&f);
  cout << "Работа функции day_of_year():\n";
  cout << "Дата: " << f.day << " " << f.month << " " << f.year
  << " соответствует " << f.yearday << "-му дню в году\n";
  p = &f;
  cout << "Проверка доступа к структуре по указателю: p=&f;\n";
  cout << "Дата: " << p->day << " " << p->month << " "
  << p->year << " соответствует " << p->yearday << "-му дню в году\n";
} 
void day_of_year (date *pd)  
// Вычисление дня в году с помощью месяца и дня.
// pd является указателем на структуру date.
{
  int i,day,leap;
  day = pd->day;
  leap = pd->year%4==0 && pd->year%100!=0 || pd->year%400==0;
  for (i=1; i < pd->month; i++) day += day_tab[leap][i];
  pd->yearday = day;
} 
void month_day (date *pd) 
// Вычисление месяца и даты с помощью даты года
// year day.
{
  int i, leap;
  leap = pd->year%4==0 && pd->year%100!=0 || pd->year%400==0;
  pd->day = pd->yearday;
  for (i=1; pd->day > day_tab[leap][i]; i++) 
         pd->day -= day_tab[leap][i];
  pd->month = i;
}
Текст этой программы можно взять здесь.

    Описание структуры начинается со служебного слова struct, за которым может следовать необязательное имя, называемое именем типа структуры (здесь это date), которое еще называется именем шаблона. Такое имя типа структуры может использоваться в дальнейшем как сокращенная запись подробного описания однотипных структур.

    За именем типа структуры идет заключенный в фигурные скобки список элементов структуры, с описанием типа каждого элемента (элементом структуры может быть переменная, массив, структура или объединение). Элементы структуры отделяются друг от друга точкой с запятой. Например:

struct date
{
  int day;
  int month;
  int year;
  int yearday;
  char mon_name[5];
};

    За правой фигурной скобкой, закрывающей список элементов, может следовать список объектов. Например, оператор struct date {...} x,y,z; определяет переменные x,y,z в качестве структур описанного типа и приводит к выделению памяти.

    Изобразим распределение памяти для структуры x типа date:


Рис.1. Распределение памяти для структуры

    Не следует полагать, что размер структуры равен сумме размеров ее членов. Вследствие выравнивания объектов разной длины в структуре могут появляться безымянные "дыры". Так, например, если переменная типа char занимает один байт, а int - четыре байта, то для структуры:

struct
{
  char c;
  int i;
}

может потребоваться восемь байт, а не пять. Правильное значение возвращает операция sizeof.

    Описание структуры, за которым не следует список объектов, не приводит к выделению памяти (как в программе выше); оно только определяет шаблон (форму) структуры. Однако, если такое описание снабжено именем типа (например, date), то это имя типа может быть использовано позднее при определении фактических экземпляров структур (определение структур d и f в программе).

    Внешнюю или статическую структуру можно инициализировать, поместив вслед за ее определением список инициализаторов для ее компонент, заключенный в фигурные скобки. В программе таким образом инициализированы структуры d и f (они являются внешними для функции main).

   date d = { 0,0,1776,186,"июл" };
   date f = { 1,9,1986,0,"сент" };  .

    Автоматические структуры инициализации не подлежат!

    Элемент структуры может быть указан в выражении с помощью конструкции вида:

    <имя структуры>.<имя элемента>.

    Структуры могут вкладываться одна в другую, но самовложение структур запрещено!

    Например, учетная карточка служащего может выглядеть так:

struct person
{
   char name[namesize]; // Имя, фамилия, отчество.
   char address[adrsize]; // Домашний адрес.
   int zipcode[2]; // Почтовый индекс.
   int s_number [2]; // Код соц.обеспечения.
   int salary[4]; // Зарплата.
   date birthdate; // Дата рождения.
   date hiredate; // Дата поступления на работу.
};
struct date
{
   int day; // День.
   char month[10]; // Месяц.
   int year; // Год.
};

    Структура person содержит две структуры типа date и наша программа должна содержать шаблон для структуры date.

    Если определить переменную Nick следующим образом:

      struct person Nick;

то Nick.birthdate.month будет обозначать месяц рождения. Операция доступа к элементу структуры "." вычисляется слева направо.

    На следующем шаге мы перечислим операции над структурами.


Предыдущий шаг Содержание Следующий шаг