logo search
HCS12 с применением языка С - royallib

3.2. Типы данных в Си

Язык Си оперирует с восемью основными типами данных, которые представлены в табл. 3.1. Тип переменной определяет число байтов в памяти микроконтроллера, которые выделяются компилятором для ее хранения.

Табл. 3.1.  Спецификация типов данных языка Си, используемых компилятором ICC12

Область памяти, отводимая для хранения объекта типа char, всегда составляет один байт. Размер области памяти, отводимой для хранения объектов int и long, определяется типом используемого компилятора. Как правило, int — машинное слово длиною в 16 бит, long двойное машинное слово, т.е. 32 бита. Формат и размер области памяти объектов float и double также зависит от типа используемого компилятора. В данном случае приведены значения для компилятора Си из среды разработки ICC12.

Служебные слово unsigned (без знака) используется вместе с целочисленными типами. Указание служебного слова unsigned перед спецификацией типа целочисленного значения определяет использование его старшего разряда. Для целых чисел со знаком старший разряд используется для хранения знака, что приводит к сужению диапазона модуля допустимых значений. В целых числах без знака старший разряд используется как дополнительный разряд числа, следовательно, диапазон допустимых значений расширяется. По умолчанию, т.е. без указания служебного слова unsigned, переменные типа char, int и long всегда считаются знаковыми. Числа в формате с плавающей запятой типов float и double также всегда знаковые.

В сочетании со спецификацией типа int возможно применение служебного слова short (короткий). Служебное слово short используется для сужения типа int до «короткого» целого. Применение служебного слова short имеет смысл, когда длина машинного слова микроконтроллера составляет четыре и более байтов. В этом случае спецификация типа short int соответствует целому числу, разрядностью в половину машинного слова. В случаях, когда машинное слово составляет два байта, спецификации типов int и short int совпадают (например, в 16-ти разрядном микроконтроллере HCS12). В некоторых компиляторах языка Си разрешается опускать слово int в спецификации типа short int и использовать одно слово short.

Слово long, обозначающее целое число, соответствующее двойному машинному слову, является таким же служебным словом как unsigned и применяется перед спецификацией типа int для его расширения до «длинного» целого (до двойного машинного слова). Однако в языке Си разрешается опускать слово int в спецификации типа long int и использовать одно слово long.

В дополнение к рассмотренным выше основным типам данных в языке Си существуют пять дополнительных типов данных:

• Array — массив, набор элементов одного типа;

• Pointer — указатель, переменная, которая содержит адрес переменной определенного типа;

• Structure — структура, набор элементов различного типа;

• Union — объединение, одна область памяти для двух различных типов данных;

• Function — функция, являясь сама определенным типом данных, может генерировать типы данных и возвращать типы данных.

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

В языке Си в простейшем случае синтаксис определения переменной или какого либо другого объекта данных выглядит так:

<спецификация типа> <идентификатор>

В более сложных случаях указывается также способ доступа к переменной и/или класс ее хранения:

<способ доступа/класс хранения> <спецификация типа> <идентификатор>

При объявлении массива может быть задано число элементов и их значения:

char a[10]

int m[] = {5,10,4000,34}

Первое поле, <способ доступа/класс хранения>, используется для задания типа памяти, куда должна быть помещена переменная. Второе поле, спецификация типа, содержит определение типа из табл. 3.1. Третье поле, идентификатор, содержит в себе придуманное программистом имя переменной. Четвертое поле, в котором проставлено численное значение или строка символов для массива, необязательное. Оно необходимо, если программист в строке объявления переменной желает также задать ее начальное значение, т.е. инициализировать переменную. Ниже приведен пример определения двухбайтовой переменной с именем «change» в целочисленном формате со знаком (тип int в соответствии с табл. 3.1):

int change;

Точка с запятой в конце строки должна быть проставлена обязательно, поскольку она обозначает завершения выражения в тексте программы на Си.

Имя переменной может быть произвольным, но оно не должно совпадать с зарезервированными в языке Си служебными словами:

auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, struct, switch, typedef, union, unsigned, void, volatile, while

Шесть слов из приведенного списка используются в Си для определения класса хранения переменной:

extern, auto, static, register, const, volatile

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

К внешнему классу хранения (extern) относятся переменные, определения которых в тексте программы размещены вне текста некоторого программного модуля, т.е. в другом файле. Переменные с внешним классом хранения размещаются в сегменте данных (т.е. в ОЗУ микроконтроллера) и сохраняются в течение всего времени выполнения программы. Областью действия переменной с внешним классом хранения является вся программа. Т.е. такая переменная доступна во всех функциях данного модуля и во всех других модулях программы.

Служебное слово auto определяет автоматический класс хранения переменной. Если при определении переменной указание на ее класс хранения отсутствует, т.е. ни одно из служебных слов не предшествует спецификации типа переменной, то по умолчанию переменной назначается автоматический класс хранения. Областью действия переменных с автоматическим классом хранения является функция (блок), в которой они определены, а также все вложенные функции (блоки). Автоматические переменные размещаются в сегменте стека на время выполнения функции, в которой они определены. После окончания выполнения функции память, отводимая под эти переменные (стек) освобождается и может быть использована для размещения других переменных. Таким образом, время жизни переменных с автоматическим классом хранения является время выполнения функции, в которой они определены. Эти переменные доступны для чтения или изменения только в тех функциях, в которых определены.

Служебное слово static в строке определения переменной обозначает статический класс ее хранения. Переменные с этим классом хранения имеют только одно отличие от переменных с автоматическим классом хранения. Статические переменные размещаются в сегменте данных (ОЗУ микроконтроллера) и сохраняют свои значения в промежутках между выполнением функций или блоков, в которых они определены. Таким образом, время жизни данных, относящихся к статическому классу хранения, совпадает с временем выполнения всей программы.

Если в определении переменной указано служебное слово register, то компилятор постарается создать код так, чтобы переменная размещалась в регистре центрального процессора. В основном это необходимо для увеличения быстродействия. Если регистры заняты (уже все используются), то переменная будет размещена в стеке, аналогично автоматическому классу хранения.

Служебное слово const указывается в определении переменных, значения которых не изменяются на протяжении исполнения программы. Эти переменные обычно помещаются в область ПЗУ микроконтроллера. Следует обратить внимание, что в некоторых аппаратных средствах отладки для инициализации начального значения переменной типа const должен быть использован режим программирования постоянной памяти микроконтроллера.

Класс хранения volatile назначается для тех переменных, которые могут изменять свое значение не в результате действия программы, а под управлением аппаратных средств микроконтроллера. Мы рассмотрим примеры с использованием переменных класса volatile при обсуждении приложений с использованием периферийных модулей МК 68HC12.

В процессе определения переменной, которое назначает область памяти и число байтов для ее хранения, можно также установить начальное численное значение этой переменной, т.е. инициализировать переменную. Например, определение целочисленной константы «change» со значением 23 может быть проведено посредством записи:

const int change = 23

После того, как мы научились задавать необходимые для использования в прикладной программе переменные, следует научиться выполнять арифметические и логические операции над этими переменными. Этим мы займемся в следующем параграфе.