В программе, показанной в листинге 10.14, одна функция отображает массив, а другая умножает каждый элемент массива на заданное значение. Поскольку первая функция не должна изменять массив, в ней используется const. Из-за того, что вторая функция намерена модифицировать массив, ключевое слово const в ней отсутствует.
Массивы и указатели 395
Листинг 10.14. Программа arf .с

Ниже приведен вывод:
Исходный массив dip:
20.000 17.660 8.200 15.300 22.220 Массив dip после вызова функции mult_array() :
50.000 44.150 20.500 38.250 55.550
Обратите внимание, что типом обеих функций является void. Функция mult_ array() предоставляет новые значения массиву dip, но не за счет применения механизма return.
Дополнительные сведения о ключевом слове const
Вы уже знаете, что ключевое слово const можно использовать для создания символических констант:
const double PI = 3.14159;
То же самое можно было бы сделать с помощью директивы #def ine, но ключевое слово const дополнительно позволяет создавать константные массивы, константные указатели и указатели на константы.
396 глава 10
В листинге 10.4 продемонстрировано применение ключевого слова const для защиты массива от модификации:
#define MONTHS 12
const int days [MONTHS] = {31, 28, 31, 30, 31,30, 31,31, 30,31, 30, 31};
Если впоследствии попытаться в коде изменить массив, на этапе компиляции будет сгенерировано сообщение об ошибке:
days[9] =44; /* ошибка на этапе компиляции */
Указатели на константы не могут использоваться для изменения значений. Взгляните на следующий код:
double rates[5] = [88.99, 100.12, 59.45, 183.11, 340.5); const double * pd = rates; // pd указывает на начало массива
Вторая строка кода объявляет, что значение типа double, на которое указывает pd, является const. Это означает, что pd нельзя применять для изменения значений, на которые он указывает:
*pd =29.89; //не разрешено
pd[2] = 222.22; // не разрешено
rates[0] = 99.99; // разрешено, т.к. rates не является const
Независимо от того, какая форма записи используется — с указателем или с массивом, pd не разрешено применять для изменения данных, на которые он указывает. Тем не менее, поскольку массив rates не был объявлен как константа, вы можете по- прежнему использовать rates для изменения значений. Кроме того, обратите внимание, что можно сделать так, чтобы pd указывал на что-нибудь другое:
pd+ +; /* теперь pd указывает на rates [1] -- разрешено */
Указатель иа констан ту обычно передается в виде параметра функции для сообщения о том, что функция не будет его применять в целях изменения данных. Например, функция show_array() из листинга 10.14 могла бы иметь такой прототип:
void show_array(const double *ar, int n);
Существует несколько правил, которые вы должны соблюдать, присваивая указатели и используя ключевое слово const. Прежде всего, указателю на константу допускается присваивание адреса либо константных, либо неконстантных данных:
double rates [5] = {88.99, 100.12, 59.45, 183.11, 340.5}; const double locked[4] = {0.08, 0.075, 0.0725, 0.07}; const double * pc = rates; // допустимо pc = locked; // допустимо
pc = &rates[3]; // допустимо
Тем не менее, обычным указателям могут быть присвоены только адреса неконстантных данных:
double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5}; const double locked[4] = {0.08, 0.075, 0.0725, 0.07}; double * pnc = rates; // допустимо
pnc = locked; //не допустимо
pnc = &rates[3]; // допустимо
Это обоснованное правило. Иначе указатель можно было бы применять для изменения данных, которые должны быть константными.
Массивы и указатели 397
Практическим следствием этих правил является то, что функция наподобие show array() может принимать в качестве фактических аргументов имена обычных массивов и константных массивов, поскольку каждый из них может быть присвоен указателю на константу:
show_array(rates, 5); // допустимо
show_array(locked, 4); // допустимо
Таким образом, использование ключевого слова const в определении параметра функции не только защищает данные, но также позволяет функции работать с массивами, которые были объявлены как const.
Однако функции вроде mult_array() не должно передаваться имя константного массива в виде аргумента:
mult_array(rates, 5, 1.2); // допустимо
mult_array(locked, 4, 1.2); // не допустимо
В стандарте С говорится о том, что попытка модификации данных const, таких как locked, с применением отличного от const идентификатора, например, формального аргумента ar функции mult_array(), приводит к неопределенному поведению.
Существуют и другие варианты использования const. К примеру, вы можете объявить и инициализировать указатель таким образом, чтобы его нельзя было заставить указывать на что-нибудь другое. Хитрость в том, где размещено ключевое слово const:
Читать дальше