A.4 const

Предыдущая  Содержание  Следующая V*D*V

const является классификатором, указывающим, что компилятор не должен допускать присвоения. Это довольно сильно отличается от действительно постоянных значений. Допускается инициализация; локальные переменные с const могут даже быть проинициализированы с помощью значений переменных:

 

int x = 10;

int f () { const int xsave = x; ... }

 

Всегда можно использовать операции явного приведения типов для обхода проверок компилятора:

 

const int cx = 10;

  (int) cx = 20;                 ошибка

  * (int *) & cx = 20;           не запрещено

 

Эти преобразования иногда необходимы при присвоении значений указателя:

 

const void * vp;              OOC_const

 

int * ip;

int * const p = ip;              ок для локальных переменных

 

  vp = ip;                       ок, присвоение блокируется

  ip = vp;                       ошибка, разрешает присвоение

  ip = (void *) vp;              ок, грубая сила

  * (const int **) & ip = vp;    ок, избыточно

  p = ip;                        ошибка, указатель заблокирован

  * p = 10;                      ок, цель не заблокирована

 

const обычно связывается с левой частью; однако, const может быть указан перед именем типа в декларации:

 

int const v [10];                десять постоянных элементов

const int * const cp = v;        постоянный указатель на постоянное значение

 

const используется для указания того, что нежелательно изменять значение после инициализации или из функции:

 

char * strcpy (char * target, const char * source);

 

Компилятор может поместить глобальные объекты в защищенный от записи сегмент, если они были защищены const целиком. Это означает, например, что компоненты структуры наследуют const:

 

const struct { int i; } c;

c.i = 10;                        ошибка

 

Это также исключает динамическую инициализацию следующего указателя:

 

void * const String;

 

Не ясно, может ли функция создавать результат с const. ANSI-C не позволяет это. GNU-C предполагает, что в этом случае функция не вызывает никаких побочных эффектов и смотрит только на её аргументы, но ни на глобальные переменные, ни на значения после указателей. Вызовы функции такого вида могут быть удалены в процессе обычного отсева подвыражений в процессе компиляции.

Поскольку значения указателей на объекты с const не могут быть присвоены незащищённым указателям, ANSI-C имеет странную декларацию для bsearch():

 

void * bsearch (const void * key,

    const void * table, size_t nel, size_t width,

    int (* cmp) (const void * key, const void * elt));

 

table[] импортируется с const, то есть её элементы не могут быть изменены и постоянная таблица может быть передана в качестве аргумента. Тем не менее, результат bsearch() указывает на элемент таблицы и не защищает его от модификации.

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

 

Предыдущая  Содержание  Следующая