Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Массивы и указатели 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.
А что произойдет, если вы не указали размер массива?
int stuff[] = {1, [6] = 23}; // что происходит?
int staff[] = {1/ [6] = 4, 9, 10}; // что происходит?
Компилятор сделает массив достаточно большим, чтобы уместить значения инициализации. Так, массив stuff будет иметь семь элементов с номерами 0-6, а массив staff — на два элемента больше, т.е. 9 элементов.
Присваивание значений элементам массива
После того, как массив был объявлен, элементам массива можно приеваиеать значения с применением их индексов. Например, в следующем фрагменте элементам массива присваиваются четные числа:
374 глава 10
Обратите внимание, что в коде используется цикл для поэлементного присваивания значений. Язык С не позволяет присваивать один массив другому как единый модуль. Кроме того, нельзя применять форму списка в фигурных скобках, кроме как при инициализации. В следующем фрагменте кода показаны некоторые недопустимые формы присваивания.
Вспомните, что последним элементом массива oxen является oxen [SIZE-1], поэтому oxen [SIZE] и yaks [SIZE] ссылаются на данные, находящиеся за последними элементами обоих массивов.
границы массива
Вы должны обеспечить, чтобы используемые индексы массива не выходили за границы, т.е. удостовериться в том, что они имеют значения, допустимые для массива. Например, предположим, что имеется следующее объявление:
int doofi[20];
После этого на вас возлагается ответственность на то, что в программе будут применяться только индексы из диапазона от 0 до 19, т.к. компилятор не обязан вас проверять. (Хотя некоторые компиляторы будут предупреждать о наличии проблемы, но продолжат компиляцию программы в любом случае.)
Читать дальшеИнтервал:
Закладка: