Читаем Программирование. Принципы и практика использования 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.

<p id="AutBody_Root553"><strong>27.5.2. Операции над байтами</strong></p>

В далеком средневековье (в начале 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 обычно влияет на гарантии, выданные конструкторами.

<p id="AutBody_Root554"><strong>27.5.3. Пример: функция strcpy</strong></p>

Определение функции strcpy представляет собой печально известный пример лаконичного стиля, который допускает язык C (и C++) .

char* strcpy(char* p, const char* q)

{

  while (*p++ = *q++);

  return p;

}

Объяснение, почему этот код на самом деле копирует С-строку q в С-строку p, мы оставляем читателям в качестве упражнения.

ПОПРОБУЙТЕ

Является ли корректной реализация функции strcpy? Объясните почему.

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

<p id="AutBody_Root555"><strong>27.5.4. Вопросы стиля</strong></p>

Мы потихоньку втягиваемся в длинные и часто яростно оспариваемые вопросы стиля, которые, впрочем, часто не имеют большого значения. Мы объявляем указатель следующим образом:

char* p; // p — указатель на переменную типа char

Мы не принимаем стиль, продемонстрированный ниже.

char *p; /* p — нечто, что можно разыменовать, чтобы получить символ */

Пробел совершенно игнорируется компилятором, но для программиста он имеет значение. Наш стиль (общепринятый среди программистов на языке С++) подчеркивает тип объявляемой переменной, в то время как альтернативный стиль (общепринятый среди программистов на языке С) делает упор на использовании переменной. Мы не рекомендуем объявлять несколько переменных в одной строке.

char c, *p, a[177], *f; /* разрешено, но может ввести в заблуждение */

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT