Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Рассмотрим программу из листинга 10.6. Она создает массив с четырьмя элементами, а затем беспечно использует значения индекса в диапазоне от -1 до 6.
Листинг 10.6. Программа bounds.с
Массивы и указатели 375
Компилятор не проверяет допустимость индексов. В стандарте языка С результат применения некорректного индекса является неопределенным. Это означает, что после запуска программа может выглядеть работоспособной, функционировать странным образом или вовсе аварийно завершиться. Ниже приведен пример вывода при использовании компилятора GCC:
valuel = 44, value2 = 88 -1 -1
0 1
1 3
2 5
3 7
4 9
5 1624678494
6 32767
valuel = 9, value2 = -1 адрес ar г[—1] : 0x7fff5fbff8сс адрес arr[4]: 0x7fff5fbff8e0 адрес valuel: 0x7fff5fbff8e0 адрес value2: 0x7fff5fbff8cc
Обратите внимание, что компилятор сохранил значение valuel непосредственно после массива, а значение value2 — прямо перед ним. (Другие компиляторы могут сохранять данные в память в другом порядке.) В этом случае, как показано в выводе, arr [-1] соответствует той же ячейке памяти, что и value2, а arr [4] — той же ячейке памяти, что и valuel. Следовательно, применение индексов, выходящих за границы массива, приводит к тому, что программа изменяет значения других переменных. Другой компилятор может дать другие результаты, включая аварийное завершение программы.
Может возникнуть вопрос, почему в С подобное разрешено. Это является следствием принятой в языке философии доверия программисту. Отсутствие проверки границ позволяет программе на С выполняться быстрее. Компилятор не всегда способен выявить все ошибки индексации, т.к. значение индекса может оставаться неопределенным до тех пор, пока не начнется выполнение программы. По этой причине для обеспечения безопасности компилятору пришлось бы добавлять дополнительный код для проверки каждого индекса во время выполнения, что приводило бы к снижению скорости выполнения. Таким образом, компилятор С доверяет программисту в том, что он корректно кодирует, и вознаграждает его более быстрой программой. Конечно, не все программисты заслуживают такого доверия, и в таких случаях могут возникать проблемы.
Запомните одну простую вещь: нумерация в массиве начинается с 0. Необходимо выработать привычку использовать символическую константу в объявлении массива и в других местах, где применяется размер массива:
376 Глава 10
Это поможет обеспечить согласованное использование размера массива повсеместно в программе.
Указание размера массива
До сих пор при объявлении массивов применялись целочисленные константы:
Что еще разрешено? До выхода стандарта С99 при объявлении массива в квадратных скобках вы должны были помещать константное целочисленное выражение — выражение, сформированное из целочисленных констант. В этом смысле выражение sizeof считается целочисленной константой, но (в отличие от такого случая в C++) значение const — нет. Кроме того, значение такого выражения должно было быть больше 0:
Как показывают комментарии, компиляторы С, соответствующие стандарту С90, не разрешают два последних объявления. Однако, начиная со стандарта С99, в языке они допускаются, но приводят к созданию нового вида массивов, которые называются массивами переменной длины. (В стандарте С11 отступили от этой смелой инициативы, сделав массивы переменной длины дополнительной, а не обязательной языковой возможностью.)
Массивы переменной длины были введены в стандарт С99 главным образом для того, чтобы дать возможность С стать лучшим языком в плане числовых вычислений. Например, массивы переменной длины облегчают преобразование существующих библиотек подпрограмм цифровых расчетов на языке FORTRAN в код С. Массивы переменной длины обладают рядом ограничений; к примеру, массив переменной длины нельзя инициализировать при его объявлении. В этой главе мы еще вернемся к массивам переменной длины после того, как вы изучите ограничения классического массива С.
Массивы и указатели 377
Многомерные массивы
Мисс Темпест Клауд, метеоролог, желает проанализировать данные об осадках за последние пять лет. Первым делом ей необходимо выбрать способ представления данных. Один из вариантов предусматривает использование 60 переменных, по одной для каждого элемента данных. (Ранее мы уже упоминали этот вариант; сейчас, как и тогда, в нем мало смысла.) Массив из 60 элементов представляется более совершенным способом, но намного лучше хранить данные для каждого года отдельно. Можно было бы применять 5 массивов по 12 элементов, но это грубый подход, который превратится в трудноразрешимую проблему, если мисс Клауд решит изучить данные об осадках за 50 лет вместо пяти. Словом, ей нужно найти что-нибудь получше.
Более эффективный подход предполагает использование массива массивов. Главный массив должен иметь пять элементов, по одному на каждый год. В свою очередь, каждый из этих элементов является 12-элементным массивом, по одному элементу на каждый месяц. Такой массив объявляется следующим образом:
float rain[5] [12]; // массив из 5 массивов по 12 элементов float
Можно взглянуть сначала на внутреннюю часть приведенного объявления, которая выделена полужирным:
float rain[5][12]; // rain - массив, содержащий пять пока невыясненных сущностей
Внутренняя часть говорит о том, что rain — это массив с пятью элементами. Но что представляет собой каждый из этих элементов? Теперь обратимся к оставшейся части объявления (снова выделенной полужирным):
float rain[5] [12]; // массив из 12 значений float
Это информирует о том, что каждый элемент имеет тип float [12], т.е. каждый из пяти элементов rain сам по себе является массивом из 12 значений float.
Согласно такой логике, rain[0], будучи первым элементом массива rain, представляет собой массив из 12 значений float. То же самое касается rain [1], rain [2] и т.д. Если rain[0] представляет собой массив, то его первым элементом будет rain [0] [0], вторым элементом — rain [0] [1] и т.д. Короче говоря, rain — это 5-эле- ментный массив из 12-элементных массивов float, rain [0] — массив из 12 элементов float, a rain [0] [0] — значение float. Для доступа, скажем, к значению в строке 2 и столбце 3 применяется запись rain [2] [3]. (Не забывайте, что отсчет начинается с 0, поэтому строка с номером 2 будет физически третьей.)
Читать дальшеИнтервал:
Закладка: