Массивы и указатели 371
Количество элементов в списке должно соответствовать размеру массива. Но что, если вы подсчитали неправильно? Давайте возвратимся к последнему примеру, как показано в листинге 10.3, сократив список инициализации до двух элементов.
Листинг 10.3. Программа somedata.c

На этот вывод выглядит следующим образом:
1 some_data[i]
0 1492
1 1066
2 0
3 0
Как видите, у компилятора не возникло никаких проблем. Когда значения в списке закончились, он инициализировал остальные элементы значением 0. Другими словами, если вы вообще не инициализируете массив, то его элементы, подобно обычным переменным, получают случайные значения из памяти, но если вы инициализируете массив частично, то оставшиеся элементы устанавливаются в 0.
Однако компилятор не настолько великодушен, если список содержит слишком много значений. Такая избыточность считается ошибкой. Тем не менее, нет никакой необходимости подвергать себя насмешкам со стороны вашего компилятора. Вместо этого вы можете позволить компилятору привести размер массива в соответствие со списком, ничего не указывая в квадратных скобках (листинг 10.4).
Листинг 10.4. Программа day mon2.c

372 глава 10
В листинге 10.4 необходимо отметить два основных момента.
• Когда вы применяете для инициализации массива пустые квадратные скобки, компилятор подсчитывает количество элементов в списке и устанавливает размер массива в полученное число.
• Обратите внимание на то, что мы делали в управляющем операторе цикла for. Из-за отсутствия уверенности в возможности корректного подсчета количества элементов мы позволили компьютеру самостоятельно определить размер массива. Операция sizeof выдает размер в байтах следующего за ней объекта или типа. Таким образом, sizeof days — это размер в байтах всего массива, а sizeof days [0] — размер в байтах одного элемента. Разделив размер всего массива на размер одного элемента, мы получаем количество элементов в массиве.
Ниже показан результат выполнения этой программы:
Месяц 1 имеет 31 день (дней).
Месяц 2 имеет 28 день (дней) .
Месяц 3 имеет 31 день (дней) .
Месяц 4 имеет 30 день (дней) .
Месяц 5 имеет 31 день (дней) .
Месяц 6 имеет 30 день (дней).
Месяц 7 имеет 31 день (дней) .
Месяц 8 имеет 31 день (дней).
Месяц 9 имеет 30 день (дней) .
Месяц 10 имеет 31 день (дней) .
Вот как! Мы указали только 10 значений, но метод с предоставлением программе возможности самостоятельно определить размер массива предотвратил попытку вывода значений за пределами массива. Это подчеркивает потенциальный недостаток автоматического подсчета: ошибки в количестве элементов могут пройти незамеченными.
Существует еще один более короткий метод инициализации массивов. Однако, поскольку он работает только для символьных строк, мы отложим его рассмотрение до следующей главы.
Назначенные инициализаторы (С99)
В стандарте С99 добавлена новая возможность — назначенные инициализаторы. Это средство позволяет выбирать, какие элементы будут инициализированы. Предположим, например, что вы хотите инициализировать только последний элемент в массиве. С помощью традиционного синтаксиса инициализации языка С понадобится также инициализировать все элементы, предшествующие последнему:
int arr[6] = {0,0,0,0,0,212}; // традиционный синтаксис
Стандарт С99 позволяет применять в списке инициализации индекс в квадратных скобках, чтобы указать конкретный элемент:
int arr[6] = {[5] = 212}; // инициализация элемента arr[5] значением 212
Как и при обычной инициализации, после того, как вы инициализируете хотя бы один элемент, оставшиеся неинициализированные элементы устанавливаются в 0. В листинге 10.5 представлен более сложный пример.

Массивы и указатели 373
Вывод отражает несколько важных характеристик назначенных инициализаторов. Во-первых, если за назначенным инициализатором находится код с дальнейшими значениями, как в последовательности [4] = 31,30,31, эти значения используются для инициализации последующих элементов. То есть после инициализации days [4] значением 31 этот код инициализирует days [5] и days [6] значениями 30 и 31, соответственно. Во-вторых, если код инициализирует отдельный элемент значением более одного раза, то актуальной будет последняя инициализация. Например, в листинге 10.5 в начале списка производится инициализация days [1] значением 28, но позже это значение переопределено назначенным инициализатором [1] =2 9.
Читать дальше