Объявление переменных в языке программирования C-51*
Описание переменных в языке программирования C имеет огромнейшее значение, так как именно оно в большинстве случаев определяет объем программы. Обычно большой объем загрузочного модуля программы вызван неправильным объявлением переменных в исходном тексте программы. Обращение к внутренним регистрам микроконтроллеров и внешним ресурсам разрабатываемого устройства тоже производится при помощи заранее объявленных переменных.
В языке программирования C51 любая переменная должна быть объявлена до первого использования этой переменной. Как уже говорилось ранее, этот язык программирования предназначен для написания программ для микроконтроллеров семейства MCS-51, поэтому в составе языка должна отображаться внутренняя структура этого семейства микроконтроллеров. Эти особенности отражены во введении новых типов данных. В остальном язык программирования C-51 не отличается от стандарта ANSI.
Объявление переменной в языке программирования C51 представляется в следующем виде:
[спецификатор класса памяти] спецификатор типа [спецификатор типа памяти] описатель [=инициатор] [,описатель [= инициатор] ]...
Описатель - идентификатор простой переменной либо более сложная конструкция с квадратными скобками, круглыми скобками или звездочкой (набором звездочек).
Спецификатор типа - одно или несколько ключевых слов, определяющие тип объявляемой переменной. В языке СИ имеется стандартный набор типов данных, используя который можно сконструировать новые (уникальные) типы данных.
Инициатор - задает начальное значение или список начальных значений, которые (которое) присваивается переменной при объявлении.
Спецификатор класса памяти - определяется одним из четырех ключевых слов языка С: auto, bit, extern, register, sbit, sfr, sfr16 static auto, extern, register, static, и указывает, каким образом будет распределяться память под объявляемую переменную, с одной стороны, а с другой, область видимости этой переменной, т.е., из каких частей программы можно к ней обратиться.
Спецификатор типа памяти - определяется одним из шести ключевых слов языка С-51: code, data, idata, bdata, xdata, pdata и указывает, в какой области памяти микроконтроллера будет размещена переменная.
Категории типов данных
Ключевые слова для определения основных типов данных
Целые типы данных: Типы данных с плавающей запятой: bit float sbit char int short long signed unsigned sfr sfr16
Переменная любого типа может быть объявлена как неизменяемая. Это достигается добавлением ключевого слова const к спецификатору типа. Объекты с типом const представляют собой данные, используемые только для чтения, т.е. этой переменной не может быть присвоено новое значение. Отметим, что если после слова const отсутствует спецификатор типа, то подразумевается спецификатор типа int. Если ключевое слово const стоит перед объявлением составных типов (массив, структура, смесь, перечисление), то это приводит к тому, что каждый элемент также должен являться немодифицируемым, т.е. значение ему может быть присвоено только один раз.
Примеры использования ключевого слова const:
const float A=2.128E-2; const B=286; //подразумевается const int B=286
Отметим, что переменные с спецификатором класса памяти размещаются во внутреннем ОЗУ. Неизменяемость контролируется только на этапе трансляции. Для размещения переменной в ПЗУ лучше воспользоваться спецификатором типа памяти code
Целые типы данных
Для определения данных целого типа используются различные ключевые слова, которые определяют диапазон значений и размер области памяти, выделяемой под переменные (табл. 6).
Таблица 6
Тип | Размер памяти в битах | Размер памяти в байтах | Диапазон значений |
---|---|---|---|
bit | 1 | от 0 до 1 | |
char | 8 | 1 | от -128 до 127 |
unsigned shar | 8 | 1 | oт 0 до 255 |
int, short | 16 | 2 | от -32768 до 32767 |
long | 32 | 4 | от -2 147 483 648 до 2 147 483 647 |
unsigned int, unsigned short | 16 | 2 | от 0 до 65535 |
unsigned long | 32 | 4 | от 0 до 4 294 967 295 |
sbit | 1 | 0 или 1 | |
sfr | 8 | 1 | oт 0 до 255 |
sfr16 | 16 | 2 | от 0 до 65535 |
Отметим, что ключевые слова signed и unsigned необязательны. Они указывают, как интерпретируется нулевой бит объявляемой переменной, т.е., если указано ключевое слово unsigned, то нулевой бит интерпретируется как часть числа, в противном случае нулевой бит интерпретируется как знаковый. В случае отсутствия ключевого слова unsigned целая переменная считается знаковой. В том случае, если спецификатор типа состоит из ключевого типа signed или unsigned и далее следует идентификатор переменной, то она будет рассматриваться как переменная типа int. Например:
unsigned int n; //Беззнаковое шестнадцатиразрядное число n unsigned int b; int c; //подразумевается signed int c unsigned d; //подразумевается unsigned int d signed f; //подразумевается signed int f
Отметим, что модификатор типа char используется для представления одиночного символа или для объявления строковых литералов. Значением объекта типа char является код (размером 1 байт), соответствующий представляемому символу.
Отметим также, что восьмеричные и шестнадцатеричные константы также могут иметь модификатор unsigned. Это достигается указанием суффикса u или U после константы, константа без этого префикса считается знаковой.
Например:
0xA8C //int signed 01786l //long signed 0xF7u //int unsigned
Числа с плавающей запятой
Для переменных, представляющих число с плавающей запятой используется модификатор типа float. Модификатор double тоже допустим в языке программирования C51, но он не приводит к увеличению точности результата.
Величина с модификатором типа float занимает 4 байта. Из них 1 бит отводится для знака, 8 бит для избыточной экспоненты и 23 бита для мантиссы. Отметим, что старший бит мантиссы всегда равен 1, поэтому он не заполняется, в связи с этим диапазон значений переменной с плавающей точкой равен от ±1.175494E-38 до ±3.402823E+38.
Пример объявления переменной с плавающей запятой:
float f, a, b;
Переменная, которая может принимать значение из некоторого списка значений, называется переменной перечислимого типа или перечислением.
Использование такого вида переменной эквивалентно применению целой знаковой переменной char или int. Это означает, что для переменной перечислимого вида будет выделен один или два байта в зависимости от максимального значения используемых этой переменной констант. В отличие от переменных целого типа, переменные перечислимого типа позволяют вместо безликих чисел использовать имена констант, которые более понятны и легче запоминаются человеком.
Например, вместо использования чисел 1,2,3,4,5,6,7 можно использовать названия дней недели: Poned, Vtorn, Sreda, Chetv, Pjatn, Subb, Voskr. При этом каждой константе будет соответствовать свое конкретное число. Однако использование имен констант приведет к более понятной программе. Более того, транслятор сам позволяет отслеживать правильность использования констант и при попытке использования константы, не входящей в объявленный заранее список, выдает сообщение об ошибке.
Переменные enum типа могут использоваться в индексных выражениях и как операнды в арифметических операциях и в операциях отношения. Например:
if(rab_ned == SUB) dejstvie = rabota [rab_ned];
При объявлении перечисления определяется тип переменной перечисления и определяется список именованных констант, называемый списком перечисления. Значением каждого имени этого списка является целое число. Объявление перечислимой переменной начинается с ключевого слова enum и может быть представлено в двух форматах:
- enum [имя типа перечисления] {список констант} имя1 [,имя2 ...];
- enum имя перечисления описатель [,описатель..];
В первом формате имена и значения констант задаются в списке констант. Необязательное имя типа объявляемой переменной - это идентификатор, который представляет собой тип переменной, соответствующий списку констант. За списком констант записывается имя одной или нескольких переменных.
Список констант содержит одну или несколько конструкций вида:
идентификатор [= константное выражение]
Каждый идентификатор - это имя константы. Все идентификаторы в списке enum должны быть уникальными. В случае если константе явным образом не задается число, то первому идентификатору присваивается значение 0, следующему идентификатору - значение 1 и т.д.
Пример объявления переменной rab_ned и типа переменных, совместимых с этой переменной, week выглядит следующим образом:
enum week {SUB = 0, /* константе SUB присвоено значение 0 */ VOS = 0, /* константе VOS присвоено значение 0 */ POND, /* константе POND присвоено значение 1 */ VTOR, /* константе VTOR присвоено значение 2 */ SRED, /* константе SRED присвоено значение 3 */ HETV, /* константе HETV присвоено значение 4 */ PJAT /* константе PJAT присвоено значение 5 */ } rab_ned;
Идентификатор, связанный с константным выражением, принимает значение, задаваемое этим константным выражением. Результат вычисления константного выражения должен иметь тип int и может быть как положительным, так и отрицательным. Следующему идентификатору в списке, если этот идентификатор не имеет своего константного выражения, присваивается значение, равное константному выражению предыдущего идентификатора плюс 1. Использование констант должно подчиняться следующим правилам:
- Объявляемая переменная может содержать повторяющиеся значения констант.
- Идентификаторы в списке констант должны быть отличны от всех других идентификаторов в той же области видимости, включая имена обычных переменных и идентификаторы из других списков констант.
- Имена типов перечислений должны быть отличны от других имен типов перечислений, структур и смесей в этой же области видимости.
- Значение может следовать за последним элементом списка перечисления.
Во втором формате для объявления переменной перечислимого типа используется уже готовый тип переменной уже объявленный ранее. Например:
enum week rab1;
К переменной перечислимого типа можно обращаться при помощи указателей. При этом необходимо заранее определить тип переменной, на которую будет ссылаться указатель. Это может быть сделано, как описывалось выше или при помощи оператора typedef. Например:
Typedef enum {SUB = 0, /* константе SUB присвоено значение 0 */ VOS = 0, /* константе VOS присвоено значение 0 */ POND, /* константе POND присвоено значение 1 */ VTOR, /* константе VTOR присвоено значение 2 */ SRED, /* константе SRED присвоено значение 3 */ HETV, /* константе HETV присвоено значение 4 */ PJAT /* константе PJAT присвоено значение 5 */ } week;
Этот оператор не объявляет переменную, а только определяет тип переменной, отличающийся от стандартного. В дальнейшем этот тип может быть использован для объявления переменных и указателей на переменные.
* Для тех читателей что вышли на эту страницу по поиску прошу обратить внимание, что здесь рассматривается не стандартный язык программирования С, а язык, адаптированный к микроконтроллерам серии MCS-51. Имеются отличия!
[Назад] [Содержание] [Вперёд]