Типы данных языка паскаль. Создание типов данных пользователя в Pascal Перечисляемый тип данных в си
При описании переменной необходимо указать ее тип. Тип переменной описывает набор значений, которые она может принимать, и действия, которые могут быть над ней выполнены. Описание типа определяет идентификатор, который обозначает тип.
Простые типы делятся на стандартные (порядковые) и перечисляемые (ограниченные).
Стандартные типы
Турбо-Паскаль имеет четыре встроенных стандартных типа: integer (целое), real (вещественное), boolean (логический) и char (символьный).
Целочисленный тип (integer)
В Турбо-Паскале имеется пять встроенных целочисленных типов: shortint (короткое целое), integer (целое), longint (длинное целое), byte (длиной в байт) и word (длиной в слово). Каждый тип обозначает определенное подмножество целых чисел, как это показано в следующей Таблице.
Встроенные целочисленные типы.
Диапазон |
Формат |
|
8 битов со знаком |
||
16 битов со знаком |
||
2147483648 +2147483647 |
32 бита со знаком |
|
8 битов без знака |
||
16 битов без знака |
Арифметические действия над операндами целочисленного типа осуществляются в соответствии со следующими правилами:
- Тип целой константы представляет собой встроенный целочисленный тип с наименьшим диапазоном, включающим значение этой целой константы.
- В случае бинарной операции (операции, использующей два операнда), оба операнда преобразуются к их общему типу перед тем, как над ними совершается действие. Общим типом является встроенный целочисленный тип с наименьшим диапазоном, включающим все возможные значения обоих типов. Например, общим типом для целого и целого длиной в байт является целое, а общим типом для целого и целого длиной в слово является длинное целое. Действие выполняется в соответствии с точностью общего типа и типом результата является общий тип.
- Выражение справа в операторе присваивания вычисляется независимо от размера переменной слева.
Операции совершаемые над целыми числами:
“+” - сложение
“-“ - вычитание
“*” - умножение
SQR - возведение в квадрат
DIV - после деления отбрасывает дробную часть
MOD - получение целого остатка после деления
ABS - модуль числа
RANDOM(X)-получение случайного числа от 0 до Х
А:=100 ; b:=60 ; a DIV b результат - 1 а MOD b результат - 40
Описываются переменные целого типа следующим образом:
var список переменных: тип;
Например: var а,р,n:integer;
Вещественный тип(real)
К вещественному типу относится подмножество вещественных чисел, которые могут быть представлены в формате с плавающей запятой с фиксированным числом цифр. Запись значения в формате с плавающей запятой обычно включает три значения - m, b и e - таким образом, что m*b е, где b всегда равен 10, а m и e являются целочисленными значениями в диапазоне вещественного типа. Эти значения m и e далее определяют диапазон и точность вещественного типа.
Имеется пять видов вещественных типов: real, singlе, duble, exnende, comp. Вещественные типы различаются диапазоном и точностью связанных с ними значений
Диапазон и десятичные цифры для вещественных типов
Диапазон |
Цифры |
|
2.9x10Е-39 до 1.7x10Е 38 1.5x10Е-45 до 3.4x10Е 38 5.0x10Е-324 до 1.7x10Е 308 3.4x10Е-493 до 1.1x10Е 403 2Е 63 до 2Е 63 |
Операции совершаемые над вещественными числами:
- Все операции допустимые для целых чисел.
- SQRT(x)-корень квадратный из числа х.
- SIN(X), COS(X), ARCTAN(X).
- LN(X)-натуральный логарифм.
- EXP(X)-экспонента Х (е х).
- EXP(X*LN(A))-возведение в степень (А х).
- Функции преобразования типов:
- TRUNC(X)-отбрасывает дробную часть;
- ROUND(X)-округление.
- Некоторые правила арифметических операций:
- Если в арифметическом действии встречаются числа типа real и integer, то результат будет иметь тип real.
- Все составные части выражения записываются в одну строку.
- Используются только круглые скобки.
- Нельзя подряд ставить два арифметических знака.
Описываются переменные вещественного типа следующим образом:
var список переменных: тип;Например:
var d,g,k:real ;Символьный тип(char)
K типу char относится любой символ заключенный в апострофы. Для представления апострофа как символьную переменную, надо заключить его в апостроф:’’’’.
Каждый символ имеет свой код и номер. Порядковые номера цифр 0,1..9 упорядочены по возрастанию. Порядковые номера букв также упорядочены по возрастанию, но не обязательно следуют друг за другом.
К символьным данным применимы знаки сравнения:
> , < , >=, <=, <> .
Например: ‘A’ < ‘W’
Функции, которые применимы к символьным переменным:
- ORD(X) - определяет порядковый номер символа Х. ord (‘a’) =97 ;
- CHR(X) - определяет символ по номеру. chr (97 ) =’a’;
- PRED(X) - выдает символ, стоящий перед символом Х. pred (‘B’) =’A’;
- SUCC(X) - выдает символ, следующий после символа Х. succ (‘A’) =’B’;
Перечислимый тип
Перечислимый тип данных назван так потому, что задается в виде перечисления констант в строго определенном порядке и в строго определенном количестве. Перечислимый тип состоит из списка констант. Переменные этого типа могут принимать значение любой из этих констант. Описание перечислимого типа имеет вид:
Type <имя типа>=(список констант) ; Var <имя переменной>:<имя типа>;где <список констант> - это особый вид констант, задаваемых через запятую и имеющих свой порядковый номер, начиная с 0.
Например:
type направление=(север, юг, запад, восток) ; месяц=(июнь,июль,август,январь) ; емкость=(ведро,бочка,канистра,бак) ; var поворот:направление; отъезд:месяц; объем:емкость; var поворот:(свер, юг, запад, восток) ; отъезд:(июнь, июль, август, январь) ; объем:(ведро, бочка, канистра, бак) ;Можно выполнить такие операторы присваивания:
Поворот:=юг; отъезд:=август; объем:=бак;
но нельзя выполнять смешанные присваивания:
Отъезд:=юг; объем:=август;
К переменным перечислимого типа применимы следующие функции:
1. ORD - порядковый номер
2. PRED - предшествующий элемент
3. SUCC - последующий элемент.
PRED (бочка) =ведро; SUCC (юг) =запад; ORD (июль) =1 ;Переменные перечислимого типа можно сравнить, так как они упорядочены и пронумерованы. Так выражения: север < юг, июнь < январь имеют значения TRUE, а юг>запад и бак<бочка значение FАLSE.
Ограниченный тип
Если переменная принимает не все значения своего типа, а только в некотором диапазоне, то ее можно рассматривать как переменную ограниченного типа. Каждый ограниченный тип задается путем накладывания ограничения на базовые типы.
Описывается так:
TYPE <имя типа>=константа1 ..константа2При этом должны выполняться следующие правила:
- Обе ограниченные константы должны быть одного типа.
- В качестве базового типа можно использовать любой простой тип, кроме действительного(real).
- Начальные значение при определении ограниченного типа не должно быть больше конечного значения.
Можно описывать сразу в разделе описания переменных:
var a,g:0 ..63 ; char1,char2:’a’..’z’.Переменными называют величины, значения которыхмогут изменяться в процессе выполнения программы. Каждая переменная задается своим уникальным именем, построенным по правилам, указанным в начале главы. Максимально возможная длина имени зависит от реализации Паскаля, теоретически можно давать переменным имена вплоть до 63 символов длиной, что едва ли актуально – обычно имена не длиннее 5-10 символов.
Поскольку любые данные в памяти компьютера хранятся в числовой форме и двоичной системе счисления, кроме имени, переменной обязательно следует присвоить и тип , определяющийдиапазон значений , принимаемых переменной, испособ ее обработки машиной. Поясним сказанное на примере. Как видно из Приложения 1, латинская большая буква "A" имеет десятичный код 65, или 01000001 в двоичном представлении. Без дополнительной информации отипе данных, хранящихся в некоторой ячейке памяти, компьютеру было бы невозможно решить, что именно представляют из себя эти данные – число 65, код символа "A" или что-то еще. В любом языке программирования, в том числе и в Паскале, существует стандартный набор типов, к которым может быть отнесена та или иная совокупность ячеек памяти. Информацию о типах данных Паскаля удобно свести в таблицу. Строки этой таблицы будут упорядочены постаршинству типов , от самого "младшего", требующего наименьшее число байт для представления, и, соответственно, представляющего наименьший диапазон возможных значений, до самого "старшего", представляющего наибольший диапазон значений. В таблице представлены не все возможные, а лишь основные типы данных Паскаля.
Ключевое слово Паскаля |
Название и описание типа |
Объем памяти, байт |
Диапазон возможных значений |
Логический: хранит одну логическую переменную | |||
Символьный: хранит код одного символа из набора ASCII-кодов |
от 0 до 255 включительно (2 8 =256) |
||
Целочисленный | |||
Целочисленный без знака |
±2 16 - диапазон вдвое больше, так как 16-й бит не занят под знак числа |
||
Длинное целое: для представления больших целочисленных значений | |||
Вещественное число с точностью представления до 11-12 знака в дробной части |
~ 2.9*10 -39 - 1.7*10 38 |
||
Вещественное число с точностью представления до 15-16 знака в дробной части |
~ 5*10 -324 – 1.7*10 308 |
||
Последовательность символов типа Charдлиной от 1 до 255 |
2-256 (данные строки + 1 байт для хранения ее длины) |
Любые строки текста, состоящие из печатаемых символов |
Теоретически для записи переменной типа Booleanбыло бы достаточно 1 бита, но минимальная адресуемая единица памяти – 1 байт (см. Приложение 1). В этом же Приложении уточните, как именно объем памяти в байтах, выделяемой под переменную, влияет на диапазон представляемых ей значений.
Целочисленные и символьные типы обобщенно называют порядковыми , подчеркивая этим, что данные типы имеют конечный набор значений, которые могут быть упорядочены или перечислены. Напомним, что вещественные значения хранятся в памяти компьютера иначе, чем целые – а именно, как совокупность мантиссы и порядка.
Разумеется, задача правильного выбора типов данных целиком ложится на программиста. Например, если некоторый счетчик в Вашей программе может принимать целочисленные значения от 1 до 100000, неправильно было бы описывать его как переменную типа Integer– ведь 2 15 =32768 и при достижении счетчиком этой величины произойдетсброс его значения, которое станет равно -32768. Разумным в данном случае было бы описание счетчика как переменной типаLongint.
Переменные описываются в программе оператором следующего вида:
var Список1:Тип1;
Список2:Тип2;
СписокN:ТипN;
Здесь список – набор имен переменных, разделенных запятыми (или одна переменная), атип – любой из рассмотренных выше типов данных. Например, конструкция
описывает 2 вещественных переменных с именами tиr, а также целочисленную переменную с именемi. Ключевое словоvarможно и продублировать, но обычно такой необходимости нет. Сокращениеvarобразовано от английского слова "Variable" (переменная).
В стандарте C++ нет типа данных, который можно было бы считать действительно символьным. Для представления символьной информации есть два типа данных, пригодных для этой цели, – это типы char и wchar_t .
Переменная типа char рассчитана на хранение только одного символа (например, буквы или пробела). В памяти компьютера символы хранятся в виде целых чисел. Соответствие между символами и их кодами определяется таблицей кодировки , которая зависит от компьютера и операционной системы. Почти во всех таблицах кодировки есть прописные и строчные буквы латинского алфавита, цифры 0, ..., 9, и некоторые специальные символы. Самой распространенной таблицей кодировки является таблица символов ASCII (American Standard Code for Information Interchange – Американский стандартный код для обмена информацией).
Так как в памяти компьютера символы хранятся в виде целых чисел, то тип char на самом деле является подмножеством типа int .
Под величину символьного типа отводится 1 байт .
Тип char может использоваться со спецификаторами signed и unsigned . В данных типа signed char можно хранить значения в диапазоне от –128 до 127. При использовании типа unsigned char значения могут находиться в диапазоне от 0 до 255. Для кодировки используется код ASCII . Символы с кодами от 0 до 31 относятся к служебным и имеют самостоятельное значение только в операторах ввода-вывода.
Величины типа char также применяются для хранения чисел из указанных диапазонов.
Тип wchar_t предназначен для работы с набором символов, для кодировки которых недостаточно 1 байта, например в кодировке Unicode . Размер типа wchar_t равен 2 байтам. Если в программе необходимо использовать строковые константы типа wchar_t , то их записывают с префиксом L , например, L " Слово ".
Например:
char c="c"; char a,b; char r={"A","B","C","D","E","F","\0"}; char s = "ABCDEF";
Логический (булевый) тип данных (тип bool)
В языке С++ используется двоичная логика ( истина , ложь ). Лжи соответствует нулевое значение , истине – единица . Величины данного типа могут также принимать значения true и false .
Внутренняя форма представления значения false соответствует 0, любое другое значение интерпретируется как true . В некоторых компиляторах языка С++ нет данного типа, в этом случае используют тип int , который при истинных значениях выдает 1, а при ложных – 0. Под данные логического типа отводится 1 байт .
Перечисляемый тип (тип enum)
Данный тип определяется как набор идентификаторов, являющихся обычными именованными целыми константами, которым приписаны уникальные и удобные для использования обозначения. Таким образом, перечисления представляют собой упорядоченные наборы целых значений. Они имеют своеобразный синтаксис и достаточно специфическую область использования.
Переменная , которая может принимать значение из некоторого списка определенных констант, называется переменной перечисляемого типа или перечислением . Данная переменная может принимать значение только из именованных констант списка. Именованные константы списка имеют тип int . Следовательно, память , соответствующая переменной перечисления, – это память , необходимая для размещения значения типа int .
Например:
enum year {winter, spring, summer, autumn}; enum week {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
Тип void
Множество значений этого типа пусто. Тип void имеет три назначения:
- указание о невозвращении функцией значения;
- указание о неполучении параметров функцией ;
- создание нетипизированных указателей .
Тип void в основном используется для определения функций , которые не возвращают значения, для указания пустого списка аргументов функции, как базовый тип для указателей и в операции приведения типов.
Тип | Обозначение | Название | Размер памяти, байт (бит) | Диапазон значений | ||
Имя типа | Другие имена | |||||
целый | int | signed | целый | 4 (32) | ||
signed int | ||||||
unsigned int | unsigned | беззнаковый целый | 4 (32) | 0 до 4 294 967 295 | ||
short | short int | короткий целый | 2 (16) | -32 768 до 32 767 | ||
signed short int | ||||||
unsigned short | unsigned short int | беззнаковый короткий целый | 2 (16) | 0 до 65 535 | ||
long | long int | длинный целый | 4 (32) | -2 147 483 648 до 2 147 483 647 | ||
signed long int | ||||||
unsigned long | unsigned long int | беззнаковый длинный целый | 4 (32) | 0 до 4 294 967 295 | ||
long long | long long int | длинный-предлинный целый | 8 (64) | -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 | ||
signed long long int | ||||||
unsigned long long | unsigned long | беззнаковый длинный-предлинный целый | 8 (64) | 0 до 18 446 744 073 709 551 615 | ||
long int | ||||||
символьный | char | signed char | байт (целый длиной не менее 8 бит) | 1 (8) | -128 до 127 | |
unsigned char | - | беззнаковый байт | 1 (8) | 0 до 255 | ||
wchar_t | - | расширенный символьный | 2 (16) | 0 до 65 535 | ||
вещественный | float | - | вещественный одинарной точности | 4 (32) | 3.4Е-38 до 3.4Е+38 (7 значащих цифр) | |
double | - | вещественный двойной точности | 8 (64) | |||
long double | - | вещественный максимальной точности | 8 (64) | 1.7Е-308 до 1.7Е+308 (15 значащих цифр) | ||
bool | - | логический | 1 (8) | true (1) или false (0) | ||
enum | - | перечисляемый | 4 (32) | -2 147 483 648 до 2 147 483 647 |
Преобразования типов
При вычислении выражений некоторые операции требуют, чтобы операнды имели соответствующий тип, в противном же случае на этапе компиляции выдается сообщение об ошибке . Например, операция взятия остатка от деления (%) требует целочисленных операндов . Поэтому в языке С++ есть возможность приведения значений одного типа к другому.
Преобразование типов – это приведение значения переменной одного типа в значение другого типа.
Выделяют явное и неявное приведения типов . При явном приведении указывается тип переменной , к которому необходимо преобразовать исходную переменную. При неявном приведении преобразование происходит автоматически, по правилам, заложенным в языке программирования С++.
Формат операции явного преобразования типов:
имя_типа (операнд)
Например, int(x), float(2/5), long(x+y/0.5) .
Пример 1 .
//Взятие цифры разряда сотых в дробном числе
#include "stdafx.h"
#include
Преобразования типов нужно применять с осторожностью, так как данная операция может приводить к потере информации . Например, после приведения длинного типа к более короткому происходит усечение информации из старших битов.
Пример 2. Временной интервал
Заданы моменты начала и конца некоторого промежутка времени в часах, минутах и секундах (в пределах одних суток). Найти продолжительность этого промежутка в тех же единицах.
Исходными данными для этой задачи являются шесть целых величин, задающих моменты начала и конца интервала, результатами – три целых величины (тип int ).
Обозначим переменные для хранения начала интервала hour1 , min1 и sec1 , для хранения конца интервала – hour2 , min2 и sec2 , а результирующие величины – hour , min и sec .
Для решения этой задачи необходимо преобразовать оба момента времени в секунды, вычесть первый из второго, а затем преобразовать результат обратно в часы, минуты и секунды. Следовательно, потребуется промежуточная переменная sum_sec , в которой будет храниться величина интервала в секундах. Она может иметь весьма большие значения, ведь в сутках 86400 секунд, что выходит за пределы типа short int . Следовательно, для этой переменной выберем длинный целый тип (long int , сокращенно long ).
Для перевода результата из секунд обратно в часы и минуты используется отбрасывание дробной части при делении целого числа на целое.
//Временной интервал. Форматированный ввод-вывод данных
#include "stdafx.h"
#include
При выполнении математических операций производится неявное ( автоматическое) преобразование типов, чтобы привести операнды выражений к общему типу или чтобы расширить короткие величины до размера целых величин, используемых в машинных командах. Выполнение преобразования зависит от специфики операций и от типа операнда или операндов .
1. Преобразование целых типов со знаком .
- Целое со знаком преобразуется к более короткому целому со знаком , с потерей информации: пропадают все разряды числа, которые находятся выше (или, соответственно – ниже) границы, определяющей максимальный размер переменной.
- Целое со знаком преобразуется к более длинному целому со знаком . Путем размножения знака. То есть все добавленные биты двоичного числа будут заняты тем же числом, которое находилось в знаковом бите : если число было положительным, то это будет, соответственно 0, если отрицательным, то 1.
- Целое со знаком к целому без знака . Первым шагом целое со знаком преобразуется к целому со знаком, соответствующему целевому типу, если этот тип данных крупнее. У получившегося значения бит знака не отбрасывается, а рассматривается равноправным по отношению к остальным битам, то есть теперь все биты образуют числовое значение.
- При преобразовании величины с плавающей точкой к целым типам она сначала преобразуется к типу long (дробная часть плавающей величины при этом отбрасывается), а затем величина типа long преобразуется к требуемому целому типу. Если значение слишком велико для long , то результат преобразования не определен. Обычно это означает, что на усмотрение компилятора может получиться любой "мусор". В реальной практике с такими преобразованиями обычно сталкиваться не приходится.
Перечисляемый тип определяется как набор идентификаторов, с точки зрения языка играющих ту же роль, что и обычные именованные константы, но связанные с этим типом. Классическое описание типа-перечисления в языке Паскаль выглядит следующим образом:
type Cardsuit = (clubs , diamonds , hearts , spades ) ;
Здесь производится объявление типа данных Cardsuit (карточная масть), значениями которого может быть любая из четырёх перечисленных констант. Переменная типа Cardsuit может принимать одно из значений clubs, diamonds, hearts, spades , допускается сравнение значений типа перечисление на равенство или неравенство, а также использование их в операторах выбора (в Паскале - case) в качестве значений, идентифицирующих варианты.
Использование перечислений позволяет сделать исходные коды программ более читаемыми, так как позволяют заменить «магические числа» , кодирующие определённые значения, на читаемые имена.
На базе перечислений в некоторых языках могут создаваться типы-множества . В таких случаях множество понимается (и описывается) как неупорядоченный набор уникальных значений типа-перечисления.
Перечисляемый тип может использоваться в объявлениях переменных и формальных параметров функций (процедур, методов). Значения перечислимого типа могут присваиваться соответствующим переменным и передаваться через параметры соответствующих типов в функции. Кроме того, всегда поддерживается сравнение значений перечислимого типа на равенство и неравенство. Некоторые языки поддерживают также другие операции сравнения для значений перечислимых типов. Результат сравнения двух перечислимых значений в таких случаях определяется, как правило, порядком следования этих значений в объявлении типов - значение, которое в объявлении типа встречается раньше, считается «меньше» значения, встречающегося позже. Иногда перечислимый тип или некоторый диапазон значений перечислимого типа также может быть использован в качестве типа индекса для массива. В этом случае для каждого значения выбранного диапазона в массиве имеется один элемент, а реальный порядок следования элементов соответствует порядку следования значений в объявлении типа.
Реализация
Обычно в процессе компиляции значения перечислений представляются при помощи целых чисел. В зависимости от конкретного языка программирования такое представление может быть либо полностью скрыто от программиста, либо доступно ему с помощью тех или иных «обходных манёвров» (например, принудительного преобразования значения типа перечисление к значению типа «целое число»), либо даже управляемо программистом (в таких случаях программист имеет возможность явно указать, какими числами будут кодироваться все или некоторые значения типа-перечисления). У всех вариантов есть свои положительные и отрицательные стороны. С одной стороны, возможность использования числовых значений констант, составляющих тип-перечисление, особенно при злоупотреблении ею, лишает смысла использование этих типов и создаёт опасность появления ошибок (когда используются числовые значения, для которых в типе нет соответствующих констант). С другой стороны, явное управление значениями даёт некоторые дополнительные возможности. Например, позволяет использовать типы-перечисления при организации интерфейса с модулями, написанными на других языках, если они используют или возвращают кодированные целыми числами значения из некоторого предопределённого набора.
Ещё одна возможность, которую дают перечислимые типы на уровне реализации языка - экономия памяти. При небольшом объёме типа-перечисления для хранения значения этого типа достаточно нескольких битов (вышеприведённый тип Cardsuit требует всего два бита на значение, в то время как стандартное целое число на большинстве используемых архитектур занимает 32 бита - в 16 раз больше), и компилятор может использовать этот факт для уплотнения хранения данных в памяти. Это может быть особенно важно, если несколько значений типов-перечислений хранятся в одной записи - уплотнение записей при обработке больших их количеств может освободить много памяти. Правда, необходимо отметить, что компиляторы обычно не реализуют эту возможность, по крайней мере, в последнее время, когда компьютерная память существенно подешевела.
Критика
Тип перечисление является традиционным для развитых языков программирования, используется достаточно широко и часто воспринимается как нечто само собой разумеющееся. Тем не менее, этот тип также не обходится без критики со стороны теоретиков и практиков программирования. Так, при разработке языка программирования Оберон перечислимые типы попали в список возможностей, которые были удалены из языка. Никлаус Вирт , разработчик языка, назвал следующие причины:
С другой стороны, например, в Java , первоначально не содержащей перечислимого типа, этот тип был впоследствии введён из соображений не только удобства, но и надёжности: проблема использования вместо перечислений групп именованных констант в том, что отсутствует контроль со стороны компилятора как за уникальностью значений констант, так и за возможностью случайного присваивания переменным значений, не соответствующих ни одной из этих констант.
Описание перечислений в различных языках
Enum cardsuit { CLUBS , DIAMONDS , HEARTS , SPADES };
Динамические языки слабой типизации с C-подобным синтаксисом (например perl или JavaScript), как правило, не имеют перечислений.
C++
Перечисления в языке C++ прямо наследуют поведение перечислений языка C, за исключением того, что перечисляемый тип в C++ - настоящий тип, и ключевое слово enum используется только при объявлении такого типа. Если при обработке параметра являющегося перечислением, какое-либо значение из перечисления не обрабатывается (например один из элементов перечисления забыли обработать в конструкции switch), то компилятор может выдать предупреждение о забытом значении.
enum Cardsuit { Clubs , Diamonds , Spades , Hearts }
Java
В первоначальной Java перечислений не было, вместо них предлагалось использовать классы со статическими константами. Начиная с версии 5 (1.5) перечисления были введены в язык, они представляют собой полноценный класс, в который можно добавлять произвольное количество полей и методов. Перечисления были введены для улучшенного контроля за типобезопасностью.
Чьё множество значений представляет собой ограниченный список идентификаторов.
Описание и использование
Перечисляемый тип определяется как набор идентификаторов, с точки зрения языка играющих ту же роль, что и обычные именованные константы, но связанные с этим типом. Классическое описание типа-перечисления в языке Паскаль выглядит следующим образом:
type Cardsuit = (clubs, diamonds, hearts, spades);
Здесь производится объявление типа данных Cardsuit (карточная масть), значениями которого может быть любая из четырёх перечисленных констант. Переменная типа Cardsuit может принимать одно из значений clubs, diamonds, hearts, spades , допускается сравнение значений типа перечисление на равенство или неравенство, а также использование их в операторах выбора (в Паскале - case) в качестве значений, идентифицирующих варианты.
Использование перечислений позволяет сделать исходные коды программ более читаемыми, так как позволяют заменить «магические числа» , кодирующие определённые значения, на читаемые имена.
На базе перечислений в некоторых языках могут создаваться типы-множества . В таких случаях множество понимается (и описывается) как неупорядоченный набор уникальных значений типа-перечисления.
Перечисляемый тип может использоваться в объявлениях переменных и формальных параметров функций (процедур, методов). Значения перечислимого типа могут присваиваться соответствующим переменным и передаваться через параметры соответствующих типов в функции. Кроме того, всегда поддерживается сравнение значений перечислимого типа на равенство и неравенство. Некоторые языки поддерживают также другие операции сравнения для значений перечислимых типов. Результат сравнения двух перечислимых значений в таких случаях определяется, как правило, порядком следования этих значений в объявлении типов - значение, которое в объявлении типа встречается раньше, считается «меньше» значения, встречающегося позже. Иногда перечислимый тип или некоторый диапазон значений перечислимого типа также может быть использован в качестве типа индекса для массива. В этом случае для каждого значения выбранного диапазона в массиве имеется один элемент, а реальный порядок следования элементов соответствует порядку следования значений в объявлении типа.
Реализация
Обычно в процессе компиляции значения перечислений представляются при помощи целых чисел. В зависимости от конкретного языка программирования такое представление может быть либо полностью скрыто от программиста, либо доступно ему с помощью тех или иных «обходных манёвров» (например, принудительного преобразования значения типа перечисление к значению типа «целое число»), либо даже управляемо программистом (в таких случаях программист имеет возможность явно указать, какими числами будут кодироваться все или некоторые значения типа-перечисления). У всех вариантов есть свои положительные и отрицательные стороны. С одной стороны, возможность использования числовых значений констант, составляющих тип-перечисление, особенно при злоупотреблении ею, лишает смысла использование этих типов и создаёт опасность появления ошибок (когда используются числовые значения, для которых в типе нет соответствующих констант). С другой стороны, явное управление значениями даёт некоторые дополнительные возможности. Например, позволяет использовать типы-перечисления при организации интерфейса с модулями, написанными на других языках, если они используют или возвращают кодированные целыми числами значения из некоторого предопределённого набора.
Ещё одна возможность, которую дают перечислимые типы на уровне реализации языка - экономия памяти. При небольшом объёме типа-перечисления для хранения значения этого типа достаточно нескольких битов (вышеприведённый тип Cardsuit требует всего два бита на значение, в то время как стандартное целое число на большинстве используемых архитектур занимает 32 бита - в 16 раз больше), и компилятор может использовать этот факт для уплотнения хранения данных в памяти. Это может быть особенно важно, если несколько значений типов-перечислений хранятся в одной записи - уплотнение записей при обработке больших их количеств может освободить много памяти. Правда, необходимо отметить, что компиляторы обычно не реализуют эту возможность, по крайней мере, в последнее время, когда компьютерная память существенно подешевела.
Критика
Тип перечисление является традиционным для развитых языков программирования, используется достаточно широко и часто воспринимается как нечто само собой разумеющееся. Тем не менее, этот тип также не обходится без критики со стороны теоретиков и практиков программирования. Так, при разработке языка программирования Оберон перечислимые типы попали в список возможностей, которые были удалены из языка. Никлаус Вирт , разработчик языка, назвал следующие причины:
С другой стороны, например, в Java , первоначально не содержащей перечислимого типа, этот тип был впоследствии введён из соображений не только удобства, но и надёжности: проблема использования вместо перечислений групп именованных констант в том, что отсутствует контроль со стороны компилятора как за уникальностью значений констант, так и за возможностью случайного присваивания переменным значений, не соответствующих ни одной из этих констант.
Описание перечислений в различных языках
Ada
В языке Ada перечисления задаются с помощью ключевого слова is и последующего списка значений через запятую:
type Cardsuit is (clubs, diamonds, hearts, spades);
и языки с C-подобным синтаксисом
enum cardsuit { CLUBS, DIAMONDS, HEARTS, SPADES };
Динамические языки слабой типизации с C-подобным синтаксисом (например perl или JavaScript), как правило, не имеют перечислений.
C++
Перечисления в языке C++ прямо наследуют поведение перечислений языка C, за исключением того, что перечисляемый тип в C++ - настоящий тип, и ключевое слово enum используется только при объявлении такого типа. Если при обработке параметра являющегося перечислением, какое-либо значение из перечисления не обрабатывается (например один из элементов перечисления забыли обработать в конструкции switch), то компилятор может выдать предупреждение о забытом значении.
Java
В первоначальной Java перечислений не было, вместо них предлагалось использовать классы со статическими константами. Начиная с версии 5 (1.5) перечисления были введены в язык, они представляют собой полноценный класс, в который можно добавлять произвольное количество полей и методов. Перечисления были введены для улучшенного контроля за типобезопасностью.
enum Cardsuit { Clubs, Diamonds, Spades, Hearts }
Haskell
В некоторых языках программирования (например, в языке Haskell) при помощи Алгебраических типов можно эмулировать перечисления. Например, так кодируется булевский тип, содержащий два идентификатора для представления значений истинности:
Data Bool = False | True
Напишите отзыв о статье "Перечисляемый тип"
Примечания
|
Отрывок, характеризующий Перечисляемый тип
– Поручите это мне, – сказала княжна Марья. – Я знаю…Пьер смотрел в глаза княжне Марье.
– Ну, ну… – говорил он.
– Я знаю, что она любит… полюбит вас, – поправилась княжна Марья.
Не успела она сказать эти слова, как Пьер вскочил и с испуганным лицом схватил за руку княжну Марью.
– Отчего вы думаете? Вы думаете, что я могу надеяться? Вы думаете?!
– Да, думаю, – улыбаясь, сказала княжна Марья. – Напишите родителям. И поручите мне. Я скажу ей, когда будет можно. Я желаю этого. И сердце мое чувствует, что это будет.
– Нет, это не может быть! Как я счастлив! Но это не может быть… Как я счастлив! Нет, не может быть! – говорил Пьер, целуя руки княжны Марьи.
– Вы поезжайте в Петербург; это лучше. А я напишу вам, – сказала она.
– В Петербург? Ехать? Хорошо, да, ехать. Но завтра я могу приехать к вам?
На другой день Пьер приехал проститься. Наташа была менее оживлена, чем в прежние дни; но в этот день, иногда взглянув ей в глаза, Пьер чувствовал, что он исчезает, что ни его, ни ее нет больше, а есть одно чувство счастья. «Неужели? Нет, не может быть», – говорил он себе при каждом ее взгляде, жесте, слове, наполнявших его душу радостью.
Когда он, прощаясь с нею, взял ее тонкую, худую руку, он невольно несколько дольше удержал ее в своей.
«Неужели эта рука, это лицо, эти глаза, все это чуждое мне сокровище женской прелести, неужели это все будет вечно мое, привычное, такое же, каким я сам для себя? Нет, это невозможно!..»
– Прощайте, граф, – сказала она ему громко. – Я очень буду ждать вас, – прибавила она шепотом.
И эти простые слова, взгляд и выражение лица, сопровождавшие их, в продолжение двух месяцев составляли предмет неистощимых воспоминаний, объяснений и счастливых мечтаний Пьера. «Я очень буду ждать вас… Да, да, как она сказала? Да, я очень буду ждать вас. Ах, как я счастлив! Что ж это такое, как я счастлив!» – говорил себе Пьер.
В душе Пьера теперь не происходило ничего подобного тому, что происходило в ней в подобных же обстоятельствах во время его сватовства с Элен.
Он не повторял, как тогда, с болезненным стыдом слов, сказанных им, не говорил себе: «Ах, зачем я не сказал этого, и зачем, зачем я сказал тогда „je vous aime“?» [я люблю вас] Теперь, напротив, каждое слово ее, свое он повторял в своем воображении со всеми подробностями лица, улыбки и ничего не хотел ни убавить, ни прибавить: хотел только повторять. Сомнений в том, хорошо ли, или дурно то, что он предпринял, – теперь не было и тени. Одно только страшное сомнение иногда приходило ему в голову. Не во сне ли все это? Не ошиблась ли княжна Марья? Не слишком ли я горд и самонадеян? Я верю; а вдруг, что и должно случиться, княжна Марья скажет ей, а она улыбнется и ответит: «Как странно! Он, верно, ошибся. Разве он не знает, что он человек, просто человек, а я?.. Я совсем другое, высшее».
Только это сомнение часто приходило Пьеру. Планов он тоже не делал теперь никаких. Ему казалось так невероятно предстоящее счастье, что стоило этому совершиться, и уж дальше ничего не могло быть. Все кончалось.
Радостное, неожиданное сумасшествие, к которому Пьер считал себя неспособным, овладело им. Весь смысл жизни, не для него одного, но для всего мира, казался ему заключающимся только в его любви и в возможности ее любви к нему. Иногда все люди казались ему занятыми только одним – его будущим счастьем. Ему казалось иногда, что все они радуются так же, как и он сам, и только стараются скрыть эту радость, притворяясь занятыми другими интересами. В каждом слове и движении он видел намеки на свое счастие. Он часто удивлял людей, встречавшихся с ним, своими значительными, выражавшими тайное согласие, счастливыми взглядами и улыбками. Но когда он понимал, что люди могли не знать про его счастье, он от всей души жалел их и испытывал желание как нибудь объяснить им, что все то, чем они заняты, есть совершенный вздор и пустяки, не стоящие внимания.
Когда ему предлагали служить или когда обсуждали какие нибудь общие, государственные дела и войну, предполагая, что от такого или такого исхода такого то события зависит счастие всех людей, он слушал с кроткой соболезнующею улыбкой и удивлял говоривших с ним людей своими странными замечаниями. Но как те люди, которые казались Пьеру понимающими настоящий смысл жизни, то есть его чувство, так и те несчастные, которые, очевидно, не понимали этого, – все люди в этот период времени представлялись ему в таком ярком свете сиявшего в нем чувства, что без малейшего усилия, он сразу, встречаясь с каким бы то ни было человеком, видел в нем все, что было хорошего и достойного любви.
Рассматривая дела и бумаги своей покойной жены, он к ее памяти не испытывал никакого чувства, кроме жалости в том, что она не знала того счастья, которое он знал теперь. Князь Василий, особенно гордый теперь получением нового места и звезды, представлялся ему трогательным, добрым и жалким стариком.
Пьер часто потом вспоминал это время счастливого безумия. Все суждения, которые он составил себе о людях и обстоятельствах за этот период времени, остались для него навсегда верными. Он не только не отрекался впоследствии от этих взглядов на людей и вещи, но, напротив, в внутренних сомнениях и противуречиях прибегал к тому взгляду, который он имел в это время безумия, и взгляд этот всегда оказывался верен.
«Может быть, – думал он, – я и казался тогда странен и смешон; но я тогда не был так безумен, как казалось. Напротив, я был тогда умнее и проницательнее, чем когда либо, и понимал все, что стоит понимать в жизни, потому что… я был счастлив».
Безумие Пьера состояло в том, что он не дожидался, как прежде, личных причин, которые он называл достоинствами людей, для того чтобы любить их, а любовь переполняла его сердце, и он, беспричинно любя людей, находил несомненные причины, за которые стоило любить их.
С первого того вечера, когда Наташа, после отъезда Пьера, с радостно насмешливой улыбкой сказала княжне Марье, что он точно, ну точно из бани, и сюртучок, и стриженый, с этой минуты что то скрытое и самой ей неизвестное, но непреодолимое проснулось в душе Наташи.
Все: лицо, походка, взгляд, голос – все вдруг изменилось в ней. Неожиданные для нее самой – сила жизни, надежды на счастье всплыли наружу и требовали удовлетворения. С первого вечера Наташа как будто забыла все то, что с ней было. Она с тех пор ни разу не пожаловалась на свое положение, ни одного слова не сказала о прошедшем и не боялась уже делать веселые планы на будущее. Она мало говорила о Пьере, но когда княжна Марья упоминала о нем, давно потухший блеск зажигался в ее глазах и губы морщились странной улыбкой.
Перемена, происшедшая в Наташе, сначала удивила княжну Марью; но когда она поняла ее значение, то перемена эта огорчила ее. «Неужели она так мало любила брата, что так скоро могла забыть его», – думала княжна Марья, когда она одна обдумывала происшедшую перемену. Но когда она была с Наташей, то не сердилась на нее и не упрекала ее. Проснувшаяся сила жизни, охватившая Наташу, была, очевидно, так неудержима, так неожиданна для нее самой, что княжна Марья в присутствии Наташи чувствовала, что она не имела права упрекать ее даже в душе своей.
Наташа с такой полнотой и искренностью вся отдалась новому чувству, что и не пыталась скрывать, что ей было теперь не горестно, а радостно и весело.
Когда, после ночного объяснения с Пьером, княжна Марья вернулась в свою комнату, Наташа встретила ее на пороге.
– Он сказал? Да? Он сказал? – повторила она. И радостное и вместе жалкое, просящее прощения за свою радость, выражение остановилось на лице Наташи.
– Я хотела слушать у двери; но я знала, что ты скажешь мне.
Как ни понятен, как ни трогателен был для княжны Марьи тот взгляд, которым смотрела на нее Наташа; как ни жалко ей было видеть ее волнение; но слова Наташи в первую минуту оскорбили княжну Марью. Она вспомнила о брате, о его любви.