- Получить ссылку
- Электронная почта
- Другие приложения
Квалификатор типа
В языке С определяются квалификаторы типа[1], указывающие на доступность и модифицируемость переменной. Стандарт С89 определяет два квалификатора: const и volatile. (C99 добавляет третий, restrict, описанный в части II.) Квалификатор типа должен предшествовать имени типа, который он квалифицирует (уточняет).
Квалификатор const
Переменная, к которой в объявлении (декларации) применен квалификатор const, не может изменять свое значение[2].
Ее можно только инициализировать, то есть присвоить ей значение в
начале выполнения программы. Компилятор может поместить переменную этого
типа в постоянное запоминающее устройство, так называемое ПЗУ (ROM,
read-only memory). Например, в объявлении
const int a=10;
создается переменная с именем а, причем ей
присваивается начальное значение 10, которое в дальнейшем в программе
изменить никак нельзя. Переменную, к которой в объявлении применен
квалификатор const, можно использовать в различных
выражениях. Однако свое значение она может получить только в результате
инициализации или с помощью аппаратно-зависимых средств.
Квалификатор const часто используется для
того, чтобы предотвратить изменение функцией объекта, на который
указывает аргумент функции. Без него при передаче в функцию указателя
эта функция может изменить объект, на который он указывает. Однако если в
объявлении параметра-указателя применен квалификатор const, функция не сможет изменить этот объект. В следующем примере функция sp_to_dash()
печатает минус вместо каждого пробела в строке, передаваемой ей как
аргумент. То есть строка "тестовый пример" будет напечатана как
"тестовый-пример". Применение квалификатора const в объявлении параметра функции гарантирует, что внутри функций объект, на который указывает параметр функции, не будет изменен.
#include <stdio.h> void sp_to_dash(const char *str); int main(void) { sp_to_dash("тестовый пример"); return 0; } void sp_to_dash(const char *str) { while(*str) { if(*str== ' ') printf("%c", '-'); else printf("%c", *str); str++; } }
Если написать sp_to_dash() таким образом, что
внутри функции строка изменяется, то еще на этапе компиляции в программе
будет обнаружена ошибка. Например, на этапе компиляции возникнет
ошибка, если написать так:
/* Неправильный пример. */ void sp_to_dash(const char *str) { while(*str) { if(*str==' ' ) *str = '-'; /* это не правильно */ printf("%c", *str); str++; } }
Квалификатор const используется в объявлениях параметров многих функций стандартной библиотеки. Например, прототип функции strlen() выглядит так:
size_t strlen(const char *str);
Применение квалификатора const в объявлении str гарантирует, что функция не изменит строку, на которую указывает str.
Если функция стандартной библиотеки не предназначена для изменения
аргумента, то практически всегда в объявлении указателя на аргумент
применяется квалификатор const.
Программист тоже может применять квалификатор const для того, чтобы гарантировать сохранность объекта. Но следует помнить, что переменная, даже если к ней применен квалификатор const,
может быть изменена в результате какого-нибудь внешнего по отношению к
программе воздействия. Например, ей может быть присвоено значение каким
либо устройством. Однако применение квалификатора const в объявлении переменной гарантирует, что ее изменение может произойти только в ходе внешнего по отношению к программе события.
Квалификатор volatile
Квалификатор volatile указывает компилятору на
то, что значение переменной может измениться независимо от программы,
т.е. вследствие воздействия еще чего-либо, не являющегося оператором
программы. Например, адрес глобальной переменной можно передать в
подпрограмму операционной системы, следящей за временем, и тогда эта
переменная будет содержать системное время. В этом случае значение
переменной будет изменяться без участия какого-либо оператора программы.
Знание таких подробностей важно потому, что большинство компиляторов С
автоматически оптимизируют некоторые выражения, предполагая при этом
неизменность переменной, если она не встречается в левой части оператора
присваивания. В этом случае при очередной ссылке на переменную может
использоваться ее предыдущее значение. Некоторые компиляторы изменяют
порядок вычислений в выражениях, что может привести к ошибке, если в
выражении присутствует переменная, вычисляемая вне программы.
Квалификатор volatile предотвращает такие изменения программы.
Квалификаторы const и volatile
могут применяться и совместно. Например, если 0x30 — адрес порта,
значение в котором может задаваться только извне, то следующее
объявление предотвратит всякую возможность нежелательных побочных
эффектов:
const volatile char *port = (const volatile char *) 0x30;
[1]Называются также классификаторами, описателями, спецификаторами.[2]На жаргоне программистов: переменная "типа" const не может изменять значение. В описании многих языков такие переменные часто называются константами. Но если исключить левые части операторов присваивания, то переменные этого "типа" могут использоваться в тех же ситуациях, что и "настоящие" переменные. В этом смысле константы являются частным случаем переменных.
Комментарии
Отправить комментарий