Переменные перечислимого типа
Переменная, которая может принимать значение из некоторого списка значений, называется переменной перечислимого типа или перечислением.
Использование такого вида переменной эквивалентно применению целой знаковой переменной char или int. Это означает, что для переменной перечислимого вида будет выделен один или два байта в зависимости от максимального значения используемых этой переменной констант. В отличие от переменных целого типа, переменные перечислимого типа позволяют вместо безликих чисел использовать имена констант, которые более понятны и легче запоминаются человеком.
При объявлении перечисления определяется тип переменной перечисления и определяется список именованных констант, называемый списком перечисления. Значением каждого имени этого списка является целое число. Объявление перечислимой переменной начинается с ключевого слова enum и может быть представлено в двух форматах:
· enum [имя типа перечисления] {список констант} имя1 [,имя2 ...];
· enum имя перечисления описатель [,описатель..];
В первом формате имена и значения констант задаются в списке констант. Необязательное имя типа объявляемой переменной - это идентификатор, который представляет собой тип переменной, соответствующий списку констант. За списком констант записывается имя одной или нескольких переменных. Список констант содержит одну или несколько конструкций вида:
идентификатор [= константное выражение]
Каждый идентификатор - это имя константы. Все идентификаторы в списке enum должны быть уникальными. В случае если константе явным образом не задается число, то первому идентификатору присваивается значение 0, следующему идентификатору - значение 1 и т.д.
Идентификатор, связанный с константным выражением, принимает значение, задаваемое этим константным выражением. Результат вычисления константного выражения должен иметь тип int и может быть как положительным, так и отрицательным. Следующему идентификатору в списке, если этот идентификатор не имеет своего константного выражения, присваивается значение, равное константному выражению предыдущего идентификатора плюс 1. Использование констант должно подчиняться следующим правилам:
1. Объявляемая переменная может содержать повторяющиеся значения констант.
2. Идентификаторы в списке констант должны быть отличны от всех других идентификаторов в той же области видимости, включая имена обычных переменных и идентификаторы из других списков констант.
3. Имена типов перечислений должны быть отличны от других имен типов перечислений, структур и смесей в этой же области видимости.
4. Значение может следовать за последним элементом списка перечисления.
Во втором формате для объявления переменной перечислимого типа используется уже готовый тип переменной уже объявленный ранее.
К переменной перечислимого типа можно обращаться при помощи указателей. При этом необходимо заранее определить тип переменной, на которую будет ссылаться указатель. Это может быть сделано, как описывалось выше или при помощи оператора typedef.
Объявление массивов в языке программирования C-51
При обработке данных достаточно часто приходится работать с рядом переменных одинакового типа (и описывающих одинаковые объекты). В этом случае эти переменные имеет смысл объединить одним идентификатором. Это позволяют сделать массивы.
Массивы - это группа элементов одинакового типа (float, char, int и т.п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве. Объявление массива имеет два формата:
спецификатор-типа описатель [константное-выражение];
спецификатор-типа описатель [ ];
Описатель - это идентификатор массива.
Спецификатор-типа задает тип элементов объявляемого массива. Элементами массива не могут быть функции и элементы типа void.
Константное-выражение в квадратных скобках задает количество элементов массива. Константное - выражение при объявлении массива может быть опущено в следующих случаях:
· при объявлении массив инициализируется,
· массив объявлен как формальный параметр функции,
· массив объявлен как ссылка на массив, явно определенный в другом файле.
В языке СИ определены только одномерные массивы, но поскольку элементом массива может быть массив, можно определить и многомерные массивы. Они формализуются списком константных выражений следующих за идентификатором массива, причем каждое константное выражение заключается в свои квадратные скобки.
Каждое константное выражение в квадратных скобках определяет число элементов по данному измерению массива, так что объявление двухмерного массива содержит два константных выражения, трехмерного - три и т.д. Отметим, что в языке СИ первый элемент массива имеет индекс равный 0.
Структуры
Работа с массивами облегчает понимание и написание программы, когда для обозначения похожих элементов используется один идентификатор. Однако в ряде случаев приходится обрабатывать разнородные элементы, описывающие один объект. В этом случае вместо массива используется структура.
Cтруктура — это составной объект, в который входят элементы любых типов, за исключением функций. В отличие от массива, который является однородным объектом, структура может быть неоднородной. Тип структуры определяется записью вида:
struct { список описаний}
В структуре обязательно должен быть указан хотя бы один компонент. Компоненты структуры называются полями структуры. Объявление полей производится в следующем виде:
тип-данных описатель;
где тип-данных указывает тип структуры для объектов, определяемых в описателях. В простейшей форме описатели представляют собой идентификаторы переменных или массивов.
Элементом структуры может быть битовое поле, обеспечивающее доступ к отдельным битам памяти. Вне структур битовые поля объявлять нельзя. Нельзя также организовывать массивы битовых полей и нельзя применять к полям операцию определения адреса. В общем случае тип структуры с битовым полем задается в следующем виде:
struct { unsigned идентификатор 1 : длина-поля 1;
unsigned идентификатор 2 : длина-поля 2; }
длина-поля задается целым выражением или константой. Эта константа определяет число битов, отведенное соответствующему полю. Поле нулевой длины обозначает выравнивание на границу следующего слова.
Структуры битовых полей могут содержать и знаковые компоненты. Такие компоненты автоматически размещаются на соответствующих границах слов, при этом некоторые биты слов могут оставаться неиспользованными.
Ссылки на поле битов выполняются точно так же, как и компоненты общих структур. Само же битовое поле рассматривается как целое число, максимальное значение которого определяется длиной поля. Например:
Cntr.Cmd=30;
Объединения (смеси)
Главной особенностью объединения является то, что для каждого из объявленных элементов этого объединения выделяется одна и та же область памяти, т.е. они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным.
Объединение применяется для следующих целей:
1. использования одной и той же области памяти для размещения переменных различного типа;
2. интерпретации представления переменной одного типа, как несколько переменных другого типа.
Объединение по описанию подобно структуре. Тип объединения может задаваться в следующем виде:
union { описание элемента 1;
...
описание элемента n; };
Доступ к элементам объединения осуществляется тем же способом, что и к структурам.
Память, которая соответствует переменной типа объединения, определяется величиной, необходимой для размещения наиболее длинного элемента объединения. Когда используется элемент меньшей длины, то переменная типа объединения может содержать неиспользуемую память. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.
Второй вариант можно проиллюстрировать следующим образом. Например, требуется передать число плавающего типа. Однако последовательный порт может передавать или принимать только однобайтовые числа. В этом случае можно воспользоваться объединением:
union {float Koeff; //Интерпретация объединения как переменной плавающего типа
char byte[4];//Интерпретация объединения как массива
} bufer; //Объявление переменной bufer
Объединение bufer позволяет последовательному порту получить отдельный доступ ко всем байтам числа bufer.Koeff начиная от младшего байта bufer.byte[0], и заканчивая старшим байтом bufer.byte[3]. В программе затем можно пользоваться загруженным числом как числом с плавающей запятой.