Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на программирование.doc
Скачиваний:
10
Добавлен:
17.04.2019
Размер:
393.22 Кб
Скачать

2.7.Объявления в языке Си. Базовые типы данных. Области значений. Описатели

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

Целый тип данных

Тип Размер памяти в байтах Диапазон значений

char 1 от 0 до 255 без знака, от -128 до 127 со знаком

int 2 от 0 до без знака, от - до -1со знаком

short 2 от -32768 до 32767

long 4 от -2 147 483 648 до 2 147 483 647

unsigned char 1 oт 0 до 255

unsigned int 2

unsigned short 2 от 0 до 65535Данные плавающего типа

Вещественный тип данных

float – 4 байта (от до ). Из них 1 байт отводится для знака, 8 бит для избыточной экспоненты и 23 бита для мантиссы. Старший бит мантиссы всегда равен 1, поэтому он не заполняется, в связи с этим диапазон значений переменной с плавающей точкой приблизительно равен от 3.14E-38 до 3.14E+38.

double – 8 байт ( от до ). Формат аналогичен формату float. Биты памяти распределяются следующим образом: 1 бит для знака, 11 бит для экспоненты и 52 бита для мантиссы. С учетом опущенного старшего бита мантиссы диапазон значений равен от 1.7E-308 до 1.7E+308.

long double – 80 бит (от до ). Формат аналогичен double. Мантисса длиннее на 16 бит.

Описатели

Описатели в языке Си позволяют объявить следующие объекты: простые переменные, массивы, указатели и функции. В простейшем случае, если объявляется простая переменная базового типа, либо структура, либо объединение, описатель представляет собой идентификатор. При этом объекту присваивается тип, заданный спецификацией типа. (int A[10], int function(), int *A)

Составной описатель — это идентификатор, дополненный более чем одним признаком типа массив, указатель или функция. (int *X[5] – массив из пяти указателей на целое, int (*X)[5] – указатель на массив из пяти целых, int *X() – функция, возвращающая указатель на значение типа целое)

Описатели с модификаторами

Модифицировать – изменить.

Модификаторы cdecl, pascal, interrupt воздействуют на идентификатор и записываются непосредственно перед ним. Модификаторы const, volatile, near, far, huge воздействуют либо на сам идентификатор, либо на указатель. Если справа от идентификатора расположен идентификатор, то модифицируется тип объекта, именуемого идентификатором. Если же справа расположен указатель, то модифицируется указатель на данный тип.

Модификаторы const и volatile

Модификатор const не допускает явного присваивания значения переменной либо других косвенных действий по изменению ее значения. (int const *p – указатель на постоянное целое)

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

Возможно одновременное использование в объявлении модификаторов const и volatile. Это означает, что значение объявляемой переменной не может модифицироваться программой, но подвержено внешним воздействиям.

Модификаторы cdecl и pascal

Из программы на Си можно обращаться к программам, написанным на других языках, и обратно. При смешивании языков программирования есть две проблемы: написание внешних имен и передача параметров. В целях совместимости языков вводятся данные модификаторы. Результатом работы компилятора языка Си является файл, содержащий объектный код программы. Файлы с таким кодом, полученные при компиляции всех исходных файлов программы, компоновщик объединяет в один выполнимый файл. При этом производится разрешение ссылок на глобальные объекты из разных исходных файлов программы. При компиляции все глобальные идентификаторы программы, т. е. имена функций и глобальных переменных, сохраняются в объектном коде и используются компоновщиком в процессе работы. По умолчанию эти идентификаторы сохраняются в своем первоначальном виде (т. е. набранные прописными, строчными буквами либо и теми, и другими). Кроме того, в качестве первого символа каждого идентификатора компилятор языка Си добавляет символ подчеркивания.

Применение модификатора pascal приводит к тому, что идентификатор преобразуется к верхнему регистру и к нему не добавляется символ подчеркивания. Этот идентификатор может использоваться в программе на языке Паскаль, то есть в объектном коде, сгенерированном компилятором языка Си, и компилятором языка Паскаль, идентификатор будет представлен идентично.

Существует опция компиляции, которая присваивает всем функциям и указателям на функции тип pascal, при этом с помощью модификатора cdecl объявляются объекты с традиционной для Си нотацией. Главная функция программы (main) должна быть всегда объявлена с модификатором cdecl, поскольку модуль поддержки выполнения передает ей управление, используя вызывающую последовательность языка Си.

Модификаторы near, far, huge

Эти модификаторы оказывают воздействие на работу с адресами объектов.

Указатель типа near — 16-битовый; для определения адреса объекта он использует смещение относительно текущего содержимого сегментного регистра. Для указателя типа near доступная память ограничена размером текущего 64-килобайтного сегмента данных.

Указатель типа far — 32-битовый; он содержит как адрес сегмента, так и смещение. При использовании указателей типа far допустимы обращения к памяти в пределах 1-мегабайтного раздела памяти, однако значение указателя типа far циклически изменяется в пределах одного 64-килобайтного сегмента.

Указатель типа huge — 32-битовый; он также содержит адрес сегмента и смещение. Значение указателя типа huge может быть изменено в пределах всего 1-мегабайтного адресного пространства. Указатель типа huge всегда хранится в нормализованном формате.

Для вызова функции типа near используются машинные инструкции ближнего вызова, для типов far и huge — дальнего.

Модификатор interrupt

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

восстановления регистров микропроцессора. Функции прерываний следует объявлять с типом возвращаемого значения void.

Объявления переменных

Простая переменная - Скалярная переменная целого или плавающего типа.

Переменная перечислимого типа - Простая переменная целого типа, принимающая значения из предопределенного набора именованных значений.

Структура - Переменная, содержащая, совокупность элементов, которые могут иметь различные типы.

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

Массив - Переменная, содержащая совокупность элементов одинакового типа.

Указатель - Переменная, которая указывает на другую переменную (содержит ее адрес).

Объявление простой переменной

Объявление простой переменной определяет имя переменной и ее тип. Можно объявить несколько переменных в одном объявлении, задавая список <идентификаторов>, разделенных запятыми.

<спецификация типа> <идентификатор> [,<идентификатор>…];

Объявление переменной перечислимого типа

При написании программ часто возникает потребность определить несколько именованных констант, для которых требуется, чтобы все они имели различные значения. Для этого удобно воспользоваться перечисляемым типом данных, все значения которого задаются списком целочисленных констант. Объявление переменной перечислимого типа задает имя переменной и определяет список именованных констант, называемый списком перечисления. Каждому элементу списка перечисления ставится в соответствие целое число. Переменная перечислимого типа может принимать только значения из своего списка перечисления. Объявление переменной перечислимого типа начинается с ключевого слова enum. enum [имя_типа] {список_констант};

Объявление структуры

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

struct [имя] {список полей}

Список полей – перечень объявлений. Каждое объявление состоит из спецификации типа, идентификатора и ;. Список полей объявлений элементов представляет собой последовательность из одного или более объявлений переменных или битовых полей. Каждая переменная, объявленная в этом списке, называется элементом структуры.

Объявление объединения

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

union. union [имя] {список полей} Значение текущего элемента объединения теряется, когда другому элементу объединения присваивается значение.

Объявление массива

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

Объявление массива определяет тип элементов массива и его имя. Оно может определять также число элементов в массиве.

[<спецификация типа>] <описатель> [<константное выражение>];

Квадратные скобки, следующие за описателем, являются элементом языка Си, а не признаком необязательности синтаксической конструкции. Константное выражение, заключенное в квадратные скобки, определяет число элементов в массиве. Индексация элементов массива начинается с нуля.

Многомерный массив, или массив массивов, объявляется путем задания последовательности константных выражений в квадратных скобках, следующей за описателем: <спецификация типа> <описатель> [<константное выражение>] {<константное выражение>]…;

Каждое константное выражение в квадратных скобках определяет число элементов в данном измерении массива.

Объявление указателя

Указатель — это переменная, предназначенная для хранения адреса объекта некоторого типа. Объявление указателя специфицирует тип объекта и имя переменной. В качестве типа может быть использован один из базовых типов, тип перечисления, пустой тип, структура или объединение. [<спецификация типа>] *<описатель>;

Объявление функции (прототип)

Объявление функции задает имя функции и тип возвращаемого значения. В определение функции так же может задаваться класс памяти функции и тип возвращаемого значения, специфицироваться класс памяти, число аргументов и их тип. В объявлении функции допустимо задавать идентификаторы и класс памяти аргументов. Если тип возвращаемого значения не указывается, то по умолчанию используется тип «целый».

Формальные параметры - это переменные, которые принимают значения, передаваемые функции при вызове в соответствии с порядком следования их имен в списке параметров. Список может быть пустым. После последнего идентификатора в списке параметров может быть троеточие. Это означает, что число параметров функции переменно, но не меньше, чем список идентификаторов до троеточия. Допускается список параметров, состоящий только из троеточия. Это значит, что число параметров может быть равным нулю. В случае, если функция не имеет аргументов, при ее объявлении рекомендуется явно указать тип void.

Тело функции - это составной оператор, который содержит операторы, определяющие действия функции и определение операторов, используемых в этой функции.

[<спецификация класса памяти>][<спецификация типа>] <описатель>([<формальные параметры>]) {<тело функции>};

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

В языке Си имеется четыре спецификации класса памяти: auto, register, static, extern.

Область действия функций, объявленных со спецификацией класса памяти extern, распространяется на все исходные файлы, которые составляют программу, такие функции могут быть вызваны из любой функции в любом исходном файле программы. Переменные классов памяти auto и register имеют локальное время жизни. Спецификации static и extern определяют объекты с глобальным временем жизни.

Объявление переменной на внешнем уровне

Объявления переменной на внешнем уровне используют спецификации класса памяти static и extern или вообще опускают их. Спецификации класса памяти auto и register не допускаются на внешнем уровне. Объявления переменных на внешнем уровне—это либо определения переменных, либо объявления, т.е. ссылки на определения, сделанные в другом месте. Определение внешней переменной—это объявление, которое вызывает выделение памяти для этой переменной и инициализирует ее.

Объявление переменной на внутреннем уровне

Любая из четырех спецификаций класса памяти может быть использована для объявления переменной на внутреннем уровне. Если спецификация класса памяти опущена в объявлении переменной на внутреннем уровне, то подразумевается класс памяти auto.

Область действия переменной распространяется на блок, в котором она объявлена, (и на все вложенные в него блоки). Переменные класса памяти auto автоматически не инициализируются, поэтому в случае отсутствия инициализации в объявлении значение

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

возможно. Использование регистровой памяти обычно ускоряет доступ к переменной и уменьшает размер выполняемого кода программы. Переменные, объявленные с классом памяти register, имеют ту же самую область действия, что и переменные auto.

Переменная, объявленная на внутреннем уровне со спецификацией класса памяти static, имеет глобальное время жизни, но ее область действия распространяется только на блок, в котором она объявлена (и на все вложенные блоки), но отличие от переменных класса памяти auto, переменные, объявленные со спецификацией класса памяти static, сохраняют свое значение при выходе из блока. Переменные класса памяти static могут быть инициализированы константным выражением. Если явной инициализации нет, то переменная класса памяти static автоматически инициализируется нулевым значением. Инициализация выполняется один раз во время компиляции и не повторяется при каждом входе в блок. Переменная, объявленная со спецификацией класса памяти extern, является ссылкой на переменную с тем же самым именем, определенную на внешнем уровне в любом исходном файле программы. Цель внутреннего объявления extern состоит в том, чтобы сделать определение переменной внешнего уровня (как правило, данное в другом исходном файле) доступным именно внутри данного блока.