14.5.2. Записи

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

К счастью, общее понятие типа записи практически одинаково в сильно и слабо типизированных языках (с некоторыми оговорками, которые мы отложим до раздела, посвященного указателям). Идея состоит в том, что в определении структурного типа перечисляются имена полей записи, и для каждого поля указывается его тип данных. После этого можно определять переменные вновь сконструированного типа и производить доступ к полям переменных. На языке Модула-2 определение структурного типа "комплексные числа" могло бы выглядеть следующим образом:

Пример 14.1. На языке Модула-2 определение структурного типа

type complex = record re: real;
im: real
end
 

Вот аналог этого определения на языке Си:

Пример 14.2. На языке Си определение структурного типа

struct complex { float re;
float im;
}
 

После этого можно объявить переменную x комплексного типа (var x: complex; или struct complex x;) и обращаться к действительной и мнимой частям x с помощью конструкции x.re (или x.im соответственно). Поскольку размер составного значения структурного типа точно специфицирован, допускается присваивание таких значений, а также функции, вырабатывающие структурные значения и т.п.

Замечание: мы все же вынуждены отметить одну (не связанную с указателями) особенность использования структурных типов в языках линии Си, отражающую, на наш взгляд, слабость типизации. Кроме корректного с точки зрения типизации отдельного определения именованного структурного типа с использованием затем этого имени при объявлении переменных, можно определять безымянный структурный тип с одновременным объявлением переменных. Например, в языке Си допустимы следующие объявления переменных x, y и z:

Пример 14.3. На языке Си определение переменных


struct { float re;
  float im;
  } x, y;
struct { float r;
  float i;
  } z;

После этих объявлений понятно, что переменные x и y имеют один и тот же тип и что, в частности, допустимо присваивание x = y. Но чтобы понять, что на самом деле таким же типом обладает и переменная z, приходится решать громоздкую задачу определения структурной эквивалентности типов, возникновения которой обычно стремятся избежать в сильно типизированных языках программирования.