Записи+с+вариантами

При реальном программировании достаточно часто возникает желание по-разному интерпретировать содержимое одной и той же области памяти в зависимости от конкретных обстоятельств. Хорошим стилем является использование каждой структурной переменной с некоторым объектом предметной области, к которой относится программа. Поля структуры в этом случае содержат требуемые характеристики объекта. Но любой объект может менять свое состояние и соответственно набор характеристик. Поэтому удобно, продолжая использовать ту же область памяти, иметь возможность понимать ее структуру и содержание таким образом, который согласуется с текущим состоянием объекта. Понятно, что для того, чтобы получить такую возможность, нужно несколько расширить средства определения структурного типа, введя вариантность соответствующей структуры. Нужно уметь специфицировать все возможные варианты структурной и типовой интерпретации переменных и значений типа записи. Естественно, что любая такая переменная, вне зависимости от ее конкретной интерпретации, будет занимать один и тот же объем памяти, определяемый "максимальным" по размеру вариантом. Наиболее строгое решение содержится в языках линии Паскаль. В определении всего структурного типа или его завершающей части можно явно указать специальное поле перечисляемого типа (дискриминант), значения которого являются метками соответствующих вариантов типа записи. Для корректного использования переменных такого типа требуется заносить в поле дискриминанта актуальное значение при изменении интерпретации переменной и руководствоваться значением дискриминанта при доступе к содержимому переменной. Вот пример определения типа записи с вариантами в языке Паскаль: code type person = record lname, fname: alfa; birthday: date; marstatus: (single, married); case sex: (male, female) of               male: (weight: real;                       bearded: boolean); female: (size: array[1..3] of integer) end code (Считается, что типы данных alfa и date уже определены.) После определения переменной типа person в любой момент можно обращаться и к полям weight и bearded, и к элементам массива size, но корректно это следует делать, руководствуясь значением дискриминанта sex. Более слабый, но эквивалентный по возможностям механизм поддерживается в языках семейства Си. В этих языках существует специальная разновидность типов данных, называемая смесью (union). Фактически, смесь - это запись с вариантами, но без явно поддерживаемого дискриминанта. По нашему мнению, решение о применении такого "облегченного" механизма было принято потому, что использование явно задаваемого дискриминанта в языках линии Паскаль все равно является необязательным, а раз так, то при желании можно просто включить дополнительное поле, значение которого будет характеризовать применимый вариант. Приведенный выше пример можно было бы переписать на языке Си следующим образом: code struct person { char lname[10], fname[10]; integer birthday; enum { single, married } marstatus; enum { male, female } sex; union { struct { float weight; integer bearded } male; integer female[3]; } pers; } code