Чтение онлайн

на главную

Жанры

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

27.5.3. Пример: функция strcpy

Определение функции

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

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

{

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

return p;

}

Объяснение, почему этот код на самом деле копирует С-строку

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

ПОПРОБУЙТЕ

Является ли корректной реализация функции

strcpy
? Объясните почему.

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

27.5.4. Вопросы стиля

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

Конструктор

Семин Никита
1. Переломный век
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Конструктор

Афганский рубеж

Дорин Михаил
1. Рубеж
Фантастика:
попаданцы
альтернативная история
7.50
рейтинг книги
Афганский рубеж

Колючка для высшего эльфа или сиротка в академии

Жарова Анита
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Колючка для высшего эльфа или сиротка в академии

Имперец. Том 4

Романов Михаил Яковлевич
3. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 4

Совок 2

Агарев Вадим
2. Совок
Фантастика:
альтернативная история
7.61
рейтинг книги
Совок 2

Кровь и Пламя

Михайлов Дем Алексеевич
7. Изгой
Фантастика:
фэнтези
8.95
рейтинг книги
Кровь и Пламя

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Внешняя Зона

Жгулёв Пётр Николаевич
8. Real-Rpg
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Внешняя Зона

Приручитель женщин-монстров. Том 1

Дорничев Дмитрий
1. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 1

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Шесть тайных свиданий мисс Недотроги

Суббота Светлана
Любовные романы:
любовно-фантастические романы
эро литература
7.75
рейтинг книги
Шесть тайных свиданий мисс Недотроги

Измена. Мой непрощённый

Соль Мари
2. Самойловы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Мой непрощённый

Внешники

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Внешники

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач