|
Программирование >> Инициализация объектов класса, структура
int ival = 1024, ival2 = 2048; Даны определения переменных: int *pi1 = &ival, *pi2 = &ival2, **pi3 = 0; Что происходит при выполнении нижеследующих операций присваивания? Допущены (a) ival = *pi3; (e) pi1 = *pi3; (b) *pi2 = *pi3; (f) ival = *pi1; (c) ival = pi2; (g) pi1 = ival; ли в данных примерах ошибки? i (d) pi2 = *pi1; (h) pi3 = &pi2; Упражнение 3.9 Работа с указателями - один из важнейших аспектов С и С++, однако в ней легко pi = &ival; допустить ошибку. Например, код pi = pi + 1024; почти наверняка приведет к тому, что pi будет указывать на случайную область памяти. Что делает этот оператор присваивания и в каком случае он не приведет к ошибке? Упражнение 3.10 Данная программа содержит ошибку, связанную с неправильным использованием int foobar(int *pi) { *pi = 1024; return *pi; int main() { int *pi2 = 0; int ival = foobar(pi2); return 0; указателей: В чем состоит ошибка? Как можно ее исправить? int *iter = &ia[0]; int *iter end = &ia[10]; while (iter != iter end) { do something with value (*iter); ++iter; Упражнение 3.8 возвращает длину строки int strlen( const char* ); сравнивает две строки int strcmp( const char*, const char* ); копирует одну строку в другую для манипулирования строками. Например: char* strcpy( char*, const char* ); Стандартная библиотека С является частью библиотеки С++. Для ее использования м1 должны включить заголовочный файл: #include <cstring> Указатель на char, с помощью которого мы обращаемся к строке, указывает на соответствующий строке массив символов. Даже когда мы пишем строковый литерал, например const char *st = Цена бут1лки вина\n ; компилятор помещает все символы строки в массив и затем присваивает st адрес первого элемента массива. Как можно работать со строкой, используя такой указатель? Обычно для перебора символов строки применяется адресная арифметика. Поскольку строка всегда заканчивается нулевым символом, можно увеличивать указатель на 1, пока очередным символом не станет нуль. Например: Упражнение 3.11 Ошибки из предыдущих двух упражнений проявляются и приводят к фатальным последствиям из-за отсутствия в С++ проверки правильности значений указателей во время работы программы. Как вы думаете, почему такая проверка не была реализована? Можете ли вы предложить некоторые общие рекомендации для того, чтобы работа с указателями была более безопасной? 3.4. Строковые типы В С++ поддерживаются два типа строк - встроенный тип, доставшийся от С, и класс string из стандартной библиотеки С++. Класс string предоставляет гораздо больше возможностей и поэтому удобней в применении, однако на практике нередки ситуации, когда необходимо пользоваться встроенным типом либо хорошо понимать, как он устроен. (Одним из примеров может являться разбор параметров командной строки, передаваем1х в функцию miain(). М1 рассмотрим это в главе 7.) 3.4.1. Встроенный строковый тип Как уже было сказано, встроенный строковый тип перешел к С++ по наследству от С. Строка символов хранится в памяти как массив, и доступ к ней осуществляется при помощи указателя типа char*. Стандартная библиотека С предоставляет набор функций int string length( const char *st ) { int cnt = 0; if ( st ) while ( *st++ ) ++cnt; return cnt; перед операцией разыменования его следует проверять: Строка встроенного типа может считаться пустой в двух случаях: если указатель на строку имеет нулевое значение (тогда у нас вообще нет никакой строки) или указывает на массив, состоящий из одного нулевого символа (то есть на строку, не содержащую ни одного значимого символа). pc1 char *p не адресует никакого массива символов char *pc1 = 0; pc2 адресует нулевой символ const char *pc2 = ; Для начинающего программиста использование строк встроенного типа чревато ошибками из-за слишком низкого уровня реализации и невозможности обойтись без адресной арифметики. Ниже м1 покажем некоторые типичные погрешности, донускаем1е новичками. Задача проста: вычислить длину строки. Первая версия неверна. #include <iostream> Исправьте ее. const char *st = Цена бут1лки вина\n ; int main() { int len = 0; while ( st++ ) ++len; cout << len << : << st; return 0; В этой версии указатель st не разыменовывается. Следовательно, на равенство 0 проверяется не символ, на который указывает st, а сам указатель. Поскольку изначально этот указатель имел ненулевое значение (адрес строки), то он никогда не станет равным нулю, и цикл будет выполняться бесконечно. while (*st++ ) { ... } st разыменовывается, и получившееся значение проверяется на истинность. Любое отличное от нуля значение считается истинным, и, следовательно, цикл заканчивается, когда будет достигнут символ с кодом 0. Операция инкремента ++ прибавляет 1 к указателю st и таким образом сдвигает его к следующему символу. Вот как может выглядеть реализация функции, возвращающей длину строки. Отметим, что, поскольку указатель может содержать нулевое значение (ни на что не указывать),
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |