3.3. Объявление типа
В языке C имеется оператор typedef, позволяющий давать новые имена типам данных. Оператор имеет следующий формат:
typedef имя-типа новое-имя
где
имя-типа– имя базового типа или описание указателей, структур, массивов, функций и объединений.
новое-имя – синоним для имени типа, который может использоваться в последующих объявлениях.
3.4. Классы памяти переменных
Помимо типа, каждая переменная в Cимеет класс памяти. Спецификациякласса памятипеременной определяет, какое время жизни она имеет (локальное или глобальное) и влияет на область действия переменной.
В языке C определены следующие спецификации класса памяти: auto,register,staticиextern.
Класс памяти переменной определяется местом его описания и ключевым словом, если оно используется. Класс памяти определяет три условия. Во-первых, от него зависит, какие функции файла имеют доступ к переменной. Если фрагмент кода может использовать определенную переменную, говорят, что переменная видима в данном разделе. Доступность переменной различным частям программы задает ее область видимости. Во-вторых, класс памяти определяет, в каком количестве мест одна и та же переменная может объявляться. Это свойство называетсясвязыванием переменной. Наконец, класс памяти определяет длительность существования переменной в памяти –продолжительностью жизни.
В языке Cпеременная может иметь одну из трехобластей видимости: в пределах файла, блока либо прототипа функции. Переменная, имеющая область видимости в пределах файла, доступна в пределах от точки определения до конца файла, содержащего определение.
Переменная, имеющая область видимости в пределах блока, доступна в пределах от точки определения до конца блока, содержащего определение. Использовавшиеся до сих пор локальные переменные, включая формальные аргументы функций, имеют область видимости в пределах блока. Именно область видимости в пределах блока делает переменные локальными и ограничивает функциями, в которых они описаны. Тело функции считается блоком, который содержит ее формальные параметры.
Область видимости прототипа функции лежит в диапазоне от точки описания переменной до конца объявления прототипа. Это означает, что при обработке аргументов прототипа функции компилятор принимает в расчет только типы. Имена, если они используются, не имеют значения.
В языке Cпеременная можетсвязыватьсяследующим образом: внешним образом, внутренним образом либо не связываться. Внешним образом связанная переменная может использоваться в любом месте программы, включающей несколько файлов. Внутренним образом связанная переменная может использоваться в любом месте единственного файла, а не связанная переменная используется только в блоке, где она описана. Для переменных с внутренним или внешним связыванием допускается более одного объявления, а переменные без связывания могут объявляться только один раз.
Понятия связывания и области видимости взаимосвязаны. Переменные с областью видимости в пределах блока или прототипа функции не связаны. Именно поэтому описания переменных без связывания и с областью видимости в пределах блока подобны.
Переменная языка Cможет иметь один из следующих видов продолжительности жизни: глобальную продолжительность жизни и локальную продолжительность жизни.
Объект с глобальным временем жизни существует и имеет значение на протяжении всего времени выполнения программы.
Локальной переменной выделяется область памяти каждый раз, когда управление передается блоку: в котором она определена. Когда управление возвращается из блока, переменная теряет свое значение.
Объявление переменных, расположенные в исходном файле вне тел всех функций (за границами описания функций), относятся к внешнему уровню, а объявления внутри тел функций относятся к внутреннему уровню.
Объявления переменной на внешнем уровнеиспользуют спецификации класса памятиstaticиexternalили вообще опускают их. Область действия переменной внешнего уровня распространяется от точки, в которой она определена, до конца исходного файла.
Если переменная на внешнем уровне (включая функцию) объявлена со спецификацией static, то она определена только в данном исходном файле, т.е. переменные с классомstaticв данном файле никак не связаны с переменными с теми же именами в других исходных файлах. Значение переменной классаstaticможет быть проинициализировано как явно, так и неявно.
Объявление переменной с классом extern(или объявление без спецификации класса памяти) делает ее доступной и в других исходных файлах. При этом переменная может быть проинициализирована и ее характеристики (например, число элементов) могут быть заданы только в одном из исходных файлов.
При объявлении переменной на внутреннем уровнеможно использовать все четыре спецификации класса памяти:auto,register,staticиextern. Если спецификация класса памяти у переменной опущена, то предполагается классauto.
Область действия переменной класса auto с локальным временем жизни распространяется на блок, в котором она объявлена и на все вложенные в него блоки. Данный класс переменных автоматически не инициализируется и в случае отсутствия операций инициализации или присваивания для данной переменной ее значение считается неопределенным.
Спецификация класса памяти registerтребует, чтобы компилятор выделил переменной память в регистре микропроцессора (если это возможно). Использование регистровой памяти обычно ускоряет доступ к переменной и уменьшает размер выполняемого кода программы. Переменные классаregisterимеют ту же самую область действия, что и переменные классаauto, и если переменная не может быть размещена на регистре, ей присваивается память классаauto(число доступных регистров зависит от компилятора и используемого микропроцессора). В регистровой памяти может быть размещена переменная размером не больше, чем размер типаint. К переменной, размещенной в регистре, нельзя применять операцию адресации. При вызове функции из блока, в котором определены регистровые переменные, содержимое регистров сохраняется в памяти, а по возвращении в блок восстанавливается.
Переменная, объявленная со спецификацией staticна внутреннем уровне, имеет глобальное время жизни, но ее действие распространяется на блок, в котором она объявлена и на все вложенные в него блоки. В отличие от переменных классаauto, переменные классаstaticсохраняют свое значение при выходе из блока. Если переменная классаstaticявно не инициализирована, ей присваивается нулевое значение. Инициализация переменной классаstaticвыполняетсятолько один разво время компиляции.
Переменная, объявленная со спецификацией externна внутреннем уровне,является ссылкой на переменную с тем же именем, объявленную на внешнем уровне в любом исходном файле программы. Цель внутреннего объявленияexternсделать доступным переменную внешнего уровня именно внутри данного блока и всех вложенных в него блоков.