- •Указатели
- •Что представляют собой указатели
- •Операторы, используемые с указателями
- •О важности базового типа указателя
- •Присваивание значений с помощью указателей
- •Указатели и массивы
- •Индексирование указателя
- •Указатели и строковые литералы
- •Все познается в сравнении
- •Массивы указателей
- •Соглашение о нулевых указателях
- •Многоуровневая непрямая адресация
- •Проблемы, связанные с использованием указателей
- •Неинициализированные указатели
- •Некорректное сравнение указателей
- •Не забывайте об установке указателей
Не забывайте об установке указателей
Следующая (некорректная) программа должна принять строку, введенную с клавиатуры, а затем отобразить ASCII-код для каждого символа этой строки. (Обратите внимание на то, что для вывода ASCII-кодов на экран используется операция приведения типов.) Однако эта программа содержит серьезную ошибку.
// Эта программа некорректна.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
char s [80];
char *p1;
p1 = s;
do {
cout << "Введите строку: ";
gets(p1); // Считываем строку.
// Выводим ASCII-значения каждого символа.
while(*p1) cout << (int) *p1++ << ' ';
cout << ' \n';
}while(strcmp (s, "конец"));
return 0;
}
Сможете ли вы сами найти здесь ошибку?
В приведенном выше варианте программы указателю p1 присваивается адрес массива s только один раз. Это присваивание выполняется вне цикла. При входе в do-while-цикл (т.е. при первой его итерации) p1 действительно указывает на первый символ массива s. Но при втором проходе того же цикла p1 указатель будет содержать значение, которое останется после выполнения предыдущей итерации цикла, поскольку указатель p1 не устанавливается заново на начало массива s. Рано или поздно граница массива s будет нарушена.
Вот как выглядит корректный вариант той же программы.
// Эта программа корректна.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
char s[80];
char *p1;
do {
p1 = s; // Устанавливаем p1 при каждой итерации цикла.
cout << "Введите строку: ";
gets(p1); // Считываем строку.
// Выводим ASCII-значения каждого символа.
while(*p1) cout << (int) *p1++ <<' ';
cout << '\n';
}while(strcmp(s, "конец"));
return 0;
}
Итак, в этом варианте программы в начале каждой итерации цикла указатель p1 устанавливается на начало строки.
Узелок на память. Чтобы использование указателей было безопасным, нужно в любой момент знать, на что они ссылаются.
