Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы ОАиП.docx
Скачиваний:
127
Добавлен:
09.03.2016
Размер:
139.71 Кб
Скачать

40. Указатели на указатели.

Концепция массивов указателей открыта и проста, поскольку индексы имеют вполне определенное значение. Тем не менее, в случае, когда один указатель указывает на другой, могут возникнуть проблемы. Указатель на указатель является формой многочисленного перенаправления или цепочки указателей. Рассмотрим рис.

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

Многочисленное перенаправление может и дальше расширяться. Но существует немного случаев, когда необходимо что-то более мощное, чем указатель на указатель. Излишнее перенаправленние приводит к концептуальным ошибкам, которые очень трудно исправлять. (Не надо путать многочисленное перенаправление со связанными списками, которые используются в базах данных.)

Переменная, являющаяся указателем на указателе должна быть описана следующим образом. Это выполняется путем помещения двух звездочек перед именем. Например, следующее объявление сообщается компилятору, что newbalance - это указатель на указатель типа float: float **newbalance; Важно понимать, что newbalance - это не указатель на число с плавающей точкой, а указатель на указатель на вещественное число.

Для получения доступа к целевому значению, косвенно указываемому указателем на указатель, следует применить оператор * два раза, как показано в следующем примере: #include <stdio.h> int main(void) { int x, *p, **q; x = 10; p = &x; q = &p; printf ("%d", **q) ; /* вывод значения x */ return 0; } Здесь p объявляется как указатель на целое, a q - это указатель на указатель на целое. Вызов printf() выводит число 10 на экран.

41.Указатели и строки.

Строка – это последовательность (массив) символов (типа char), которая заканчивается специальным символом – признаком конца строки. Это символ записывается как '\0' (не путайте с символом переноса строки'\n') и равен 0. При вводе строки символ конца строки добавляется автоматически. Все функции работы со строками – и стандартные, и создаваемые программистом – должны ориентироваться на этот символ. Если требуется сформировать новую строку, то обязательно надо добавлять признак конца строки. Если этого не сделать, то при дальнейшей работе возникнут ошибки.

'a'

// Символьная константа - один символ

"a"

// Строковый литерал - массив из двух символов 'a' и '\0', заменяется на адрес.

char str[51];

// Объявление строки

char *str;

// Нельзя, т.к. не выделяется память под элементы строки

char *str = "abcd";

// Можно, но очень осторожно!

char *str1 = "abc", *str2 = "abc";

// Не известно, будет ли выполняться str1 == str2?

Строковым литералом называется последовательность символов, заключённых в двойные кавычки. В строковом литерале на один символ больше, чем используется при его записи – добавляется символ '\0'.

Тип строкового литерала есть «массив с надлежащим количество константных символов». Строковый литерал можно присвоить переменной типа char *. Это разрешается, потому что в предыдущих определениях С иC++ типом строкового литерала был char *. Однако изменение строкового литерала через такой указатель является ошибкой.

char *str = "С & С++";

str[2] = '?';

// Ошибка времени выполнения!

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

char str[] = "С & С++";

// Массив из 8 символов

str[2] = '?';

// Правильно

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

const char *error_massage()

{ return "Недостаточно параметров"; }

// После выхода из функции память, содержащая строку, не будет освобождена