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

Применение модификатора const помогает выявить нежелательные присваивания значений переменным. Переменные, объявленные с модификатором const, могут быть загружены в ячейки постоянной памяти (ПЗУ).

Модификатор volatile противоположен по смыслу модификатору const. Он указывает на то, что значение переменной может быть изменено; но не только непосредственно программой, а также и внешним воздействием, например программой обработки прерываний, либо, если переменная соответствует порту ввода/вывода, обменом с внешним устройством. Объявление объекта с модификатором volatile предупреждает компилятор языка Си, что не следует делать предположений относительно стабильности значения объекта в момент вычисления содержащего его выражения, т. к. значение может (теоретически) измениться в любой момент. Для выражений, содержащих объекты типа volatile, компилятор языка Си не будет применять методы оптимизации, а сами объекты не будет загружать в машинные регистры.

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

Если с модификатором const или volatile объявляется переменная составного типа, то действие модификатора распространяется на все ее составляющие элементы. Возможно применение модификаторов const и volatile в составе объявления typedef.

Примечание. При отсутствии в объявлении спецификации типа и наличии модификатора const или volatile подразумевается спецификация типа int.

Примеры:

float const pi = 3.1415926;

const maxint = 32767;

/* указатель с неизменяемым значением*/

char *const str = 'Здравствуй, мир!';

/* указатель на неизменяемую строку */

char const *str2 = 'Здравствуй, мир!';

С учетом приведенных объявлений следующие операторы недопустимы:

pi = 3.0;/* Присвоение значения константе */

i = maxini--; /* Уменьшение константы */

str = 'Привет!'; /* Переназначение указателя */

Однако вызов функции strcpy(str,'Привет!') допустим, т. к. в данном случае осуществляется посимвольное копирование строки 'Привет!' в область памяти, на которую указывает str. Поскольку компилятор 'не знает', что делает функция strcpy, он не считает эту ситуацию недопустимой.

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

Пример:

volatile int ticks;

void interrupt timer()

{

ticks ++;

}

wait(int interval)

{

ticks = 0;

while ( ticks < interval );

}

Функция wait будет 'ждать' в течение времени, заданного параметром interval при условии, что функция timer корректно связана с аппаратным прерыванием от таймера. Значение переменной ticks изменяется в функции timer каждый раз при наступлении прерывания от таймера. Модификатор interrupt описан в разделе 3.3.3.5.

Если бы переменная ticks была объявлена без модификатора volatile, то компилятор языка Си с высоким уровнем оптимизации вынес бы за пределы цикла while сравнение переменных ticks и interval, поскольку в теле цикла их значения не изменяются. Это привело бы к зацикливанию программы.

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

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

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

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

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

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

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

Если модификатор pascal применяется к идентификатору функции, то он оказывает влияние также и на передачу аргументов. Засылка аргументов в стек производится в этом случае не в обратном порядке, как принято в компиляторах языка Си в СП MSC и СП ТС, а в прямом—первым засылается в стек первый аргумент.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату
×