В некоторых случаях модель памяти может повлиять на поведение указателей и ваши возможности по их использованию. Основная проблема возникает при инкрементировании указателя за пределы сегмента. Рассмотрение особенностей каждой из 16-разрядных моделей памяти выходит за рамки этой книги. Главное, чтобы вы знали, что, если вам придется работать в 16-разрядной среде и ориентироваться на процессоры семейства Intel 8086, вы должны изучить документацию, прилагаемую к используемому вами компилятору, и подробно разобраться в моделях памяти и их влиянии на указатели.
И последнее. При написании программ для современной 32-разрядной среды необходимо знать, что в ней используется единственная модель организации памяти, которая называется
Можно создать указатель, который будет ссылаться на другой указатель, а тот — на конечное значение. Эту ситуацию называют
При использовании непрямой адресации можно организовать любое желаемое количество уровней, но, как правило, ограничиваются лишь двумя, поскольку увеличение числа уровней часто ведет к возникновению концептуальных ошибок.
Переменную, которая является указателем на указатель, нужно объявить соответствующим образом. Для этого достаточно перед ее именем поставить дополнительный символ "звездочка"(
int **balance;
Необходимо помнить, что переменная
Чтобы получить доступ к значению, адресуемому указателем на указатель, необходимо дважды применить оператор
// Использование многоуровневой непрямой адресации.
#include
using namespace std;
int main()
{
int x, *p, **q;
x = 10;
p = &x
q = &p
cout << **q; // Выводим значение переменной x.
return 0;
}
Здесь переменная
Для программиста нет ничего более страшного, чем "взбесившиеся" указатели! Указатели можно сравнить с энергией атома: они одновременно и чрезвычайно полезны и чрезвычайно опасны. Если проблема связана с получением указателем неверного значения, то такую ошибку отыскать труднее всего.
Трудности выявления ошибок, связанных с указателями, объясняются тем, что сам по себе указатель не обнаруживает проблему. Проблема может проявиться только косвенно, возможно, даже в результате выполнения нескольких инструкций после "крамольной" операции с указателем. Например, если один указатель случайно получит адрес "не тех" данных, то при выполнении операции с этим "сомнительным" указателем адресуемые данные могут подвергнуться нежелательному изменению, и, что самое здесь неприятное, это "тайное" изменение, как правило, становится явным гораздо позже. Такое "запаздывание" существенно усложняет поиск ошибки, поскольку посылает вас по "ложному следу". К тому моменту, когда проблема станет очевидной, вполне возможно, что указатель-виновник внешне будет выглядеть "безобидной овечкой", и вам придется затратить еще немало времени, чтобы найти истинную причину проблемы.
Поскольку для многих работать с указателями — значит потенциально обречь себя на поиски ответа на вопрос "Кто виноват?", мы попытаемся рассмотреть возможные "овраги" на пути отважного программиста и показать обходные пути, позволяющие избежать изматывающих "мук творчества".
Классический пример ошибки, допускаемой при работе с указателями, — использование
// Эта программа некорректна.
int main()
{
int х, *р;
х = 10;
*р = х; // На что указывает переменная р?
return 0;
}