Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A.doc
Скачиваний:
36
Добавлен:
09.04.2015
Размер:
5.6 Mб
Скачать

170 Глава 4

чать страну. Если предположить, что вы — настолько же успешный продавец, как и фермер, то выращивание такого количества бобов, в конце концов, станет оказывать влияние на озоновый слой.

Массивы хранятся в памяти так, что самый правый индекс растет быстрее всего. То есть массив data [3] [4] — это трехмерный массив, состоящий из массивов по че- тыре элемента в каждом. Организация такого массива показана на рис. 4.4.

Элементы массива располагаются в непрерывном блоке памяти, как показано стре- лочками на рис. 4.4. Первый индекс выбирает определенную строку внутри массива, а второй индекс выбирает элемент внутри строки.

Обратите внимание, что двумерный массив в родном С++ — на самом деле одномер- ный массив, состоящий из одномерных массивов. Массив с тремя измерениями в род- ном С++ — это одномерный массив элементов, в котором каждый элемент представля- ет собой одномерный массив одномерных массивов. Большую часть времени вам не придется об этом беспокоиться, но как вы увидите позднее, массивы C++/CLI отлича- ются от массивов С++. Из сказанного следует, что для массива, показанного на рис. 4.4, выражения data [ 0 ], data [ 1 ] и data [ 2 ] представляют одномерные массивы.

Инициализация многомерных массивов

Для того чтобы инициализировать многомерный массив, используется расширен- ный метод инициализации одномерных массивов. Например, вы можете инициализи- ровать двумерный массив data с помощью следующего объявления:

То есть, инициализация значений каждой строки массива содержится внутри соб- ственной пары фигурных скобок. Поскольку в каждой строке четыре элемента, в каждой группе присутствует по четыре значения инициализации, и поскольку строк всего две, внутри скобок находится две группы инициализирующих значение, разде- ленных запятой.

Массивы, строки и указатели 172

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

Я дополнил пробелами списки инициализации, чтобы показать, где пропущены значения. Элементы data[0] [3], data[l] [2] и data[l] [3] не получают инициали- зирующих значений и потому равны нулю.

Если вы хотите инициализировать весь массив нулевыми значениями, вы можете написать просто:

Если вы инициализируете массивы с большим числом измерений, помните, что вы должны указать столько вложенных фигурных скобок для групп инициализирую- щих значений, сколько в массиве измерений.

Вы можете использовать один двумерный массив для сохранения нескольких строк в стиле С. Как это работает, можно увидеть на примере.

173 Глава 4

Описание полученных результатов

Помимо развлекательного значения, главное, что интересно в этом примере — объ- явление массива stars. Это двумерный массив элементов типа char, который может содержать до шести строк, каждая из которых имеет до 80 символов длиной (вклю- чая ограничивающий нулевой символ, автоматически добавляемый компилятором). Инициализирующие строки массива заключены в кавычки и разделены запятыми.

Один из недостатков подобного применения массивов заключается в том, что значительная часть памяти не используется. Все строки короче 80 символов и потому оставшиеся избы- точные элементы массивов расходуются впустую.

Вы можете также позволить компилятору определить, сколько именно строк не- обходимо поместить в массив, пропустив величину первого измерения массива и объ- явив его следующим образом:

Это заставит компилятор определить первое измерение так, чтобы уместить необ- ходимое количество инициализированных строк. Поскольку их всего шесть, резуль- тат будет тем же самым, но это исключит вероятность ошибки. Вы не можете про- пустить оба измерения массива. В массиве из двух или более измерений самое правое всегда должно быть определено.

Обратите внимание на точку с запятой в конце объявления. О ней легко забыть при иници- ализации значений массива.

Когда вам необходимо сослаться на строку при выводе в следующем операторе, достаточно указать только значение первого индекса:

Значение с одним индексом выбирает конкретный 80-символьный подмассив, а операция вывода отображает его содержимое вплоть до нулевого символа. Индекс указан как dice - 1, потому что dice имеет значения от 1 до б, в то время как значе- ния индекса варьируются от 0 до 5.

Косвенный доступ к данным

Переменные, с которыми вы имели дело до сих пор, обеспечивали вам возмож- ность именовать некоторое место в памяти, в котором можно сохранять данные определенного типа. Содержимое переменной либо вводилось из некоторого внеш- него источника, такого как клавиатура, либо вычислялось на основе других введен- ных значений. Но есть и другой вид переменных С++, не хранящих в себе данные, которые вы обычно вводите для вычислений, но значительно повышающих мощь и гибкость ваших программ. Переменные такого рода называются указателями.

Массивы, строки и указатели 174

Что такое указатель?

Каждое место в памяти, которое вы используете для хранения данных, имеет адрес. Адрес предоставляет возможность для оборудования компьютера обращаться к определенному элементу данных. Указатель — это переменная, которая сохраняет адрес другой переменной определенного типа. Переменная-указатель обладает име- нем, как и любая другая переменная, и также имеет тип, определяющий то, на какого рода данные она может указывать. Переменная, являющаяся указателем, содержащим адрес местоположения в памяти, которое хранит значение типа int, называется "ука- зателем на int".

Объявление указателей

Объявления указателей подобно объявлению обычных переменных, за исключе- нием того, что имя дополняется впереди звездочкой, говорящей о том, что данная переменная является указателем. Например, чтобы объявить указатель pnumber типа long, можно использовать следующий оператор:

Это объявление записано со звездочкой, расположенной ближе к имени перемен- ной. Если хотите, можете также написать так:

Компилятору это безразлично. Однако типом переменной pnumber является "ука- затель на long", что часто обозначается помещением звездочки ближе к имени типа. Не важно, какой стиль вы предпочтете — важно придерживаться его согласованно.

Можно смешивать объявления обычных переменных и указателей в одном опера- торе, например:

Этот оператор, как и ранее, объявляет указатель pnumber типа "указатель на long", но также объявляет переменную number типа long. В конечном итоге, вероят- но, лучше все-таки объявлять указатели отдельно от других переменных; в противном случае такой оператор может ввести в заблуждение в отношении типа объявляемых переменных, особенно если вы предпочитаете размещать * рядом с именем типа. Следующие операторы, безусловно, выглядят яснее, к тому же размещение объявле- ния в отдельных строках позволяет вам добавить им индивидуальные комментарии, что облегчает чтение программы.

В С++ существует общепринятое соглашение — называть переменные-указатели именами, начинающимися с р. Это позволяет сразу увидеть, какие переменные явля- ются указателями, что, в свою очередь, упрощает восприятие программ.

Давайте разберем пример, демонстрирующий работу указателей, не задумываясь пока, для чего он нужен. Я продемонстрирую применение указателей очень кратко. Предположим, что у вас есть целочисленная переменная типа long по имени number, объявленная выше и содержащая значение 99. Кроме того, у вас есть указатель на long по имени pnumber, который вы можете использовать для хранения адреса пере- менной number. Но как получить адрес этой переменной?