Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

res[sz–1]=0;

return res;

}

Правильный ли ответ мы получили? Кто вызовет функцию

free
для строки, которую вернула функция
cat
?

ПОПРОБУЙТЕ

Протестируйте функцию

cat
. Почему в первой инструкции мы добавляем число 2? Мы сделали глупую ошибку в функции
cat
, найдите и устраните ее. Мы “забыли” прокомментировать код. Добавьте соответствующие комментарии, предполагая, что читатель знает стандартные функции для работы с С-строками.

27.5.1. Строки в стиле языка С и ключевое слово const

Рассмотрим следующий пример:

char* p = "asdf";

p[2] = 'x';

В языке С так писать можно, а в языке С++ — нет. В языке C++ строковый литерал является константой, т.е. неизменяемой величиной, поэтому оператор p
[2]='x'
(который пытается превратить исходную строку в строку "asxf") является недопустимым. К сожалению, некоторые компиляторы пропускают присваивание указателю
p
, что приводит к проблемам. Если вам повезет, то произойдет ошибка на этапе выполнения программы, но рассчитывать на это не стоит. Вместо этого следует писать так:

const char* p = "asdf"; // теперь вы не сможете записать символ

// в строку "asdf" с помощью указателя p

Эта рекомендация относится как к языку C, так и к языку C++.

Функция

strchr
из языка C порождает аналогичную, но более трудноуловимую проблему. Рассмотрим пример.

char* strchr(const char* s,int c); /* найти c в константной строке s

(
не C++) */

const char aa[] = "asdf"; /* aa — массив констант */

char* q = strchr(aa,'d'); /* находит символ 'd' */

*q = 'x'; /* изменяет символ 'd' в строке aa на 'x' */

Опять-таки, этот код является недопустимым ни в языке С, ни в языке С++, но компиляторы языка C не могут найти ошибку. Иногда это явление называют трансмутацией (transmutation): функция превращает константы в не константы, нарушая разумные предположения о коде.

В языке C++ эта проблема решается с помощью немного измененного объявления стандартной библиотечной функции

strchr
.

char const* strchr(const char* s, int c); // найти символ c

// в константной строке s

char* strchr(char* s, int c); // найти символ c в строке s

Аналогично объявляется функция

strstr
.

27.5.2. Операции над байтами

В далеком средневековье (в начале 1980-х годов), еще до изобретения указателя

void*
, программисты, работавшие на языках C (и C++), для манипуляции байтами использовали строки. В настоящее время основные стандартные библиотечные функции для работы с памятью имеют параметры типа
void*
и возвращают указатели типа
void*
, чтобы предупредить пользователей о непосредственной работе с памятью без контроля типов.

/* копирует n байтов из строки s2 в строку s1 (как функция strcpy): */

void* memcpy(void* s1, const void* s2, size_t n);

/* копирует n байтов из строки s2 в строку s1

(диапазон [s1:s1+n] может перекрываться с диапазоном [s2:s2+n]): */

void* memmove(void* s1, const void* s2, size_t n);

/* сравнивает n байтов из строки s2 в строку s1

(как функция strcmp): */

int memcmp(const void* s1, const void* s2, size_t n);

/* находит символ c (преобразованный в тип unsigned char)

среди первых n байтов строки s: */

void* memchr(const void* s, int c, size_t n);

/* копирует символ c (преобразованный в тип unsigned char)

в каждый из n байтов строки, на который ссылается указатель s: */

void* memset(void* s, int c, size_t n);

Не используйте эти функции в программах на языке C++. В частности, функция

memset
обычно влияет на гарантии, выданные конструкторами.

  • Читать дальше
  • 1
  • ...
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: