Помните, в разделе 3.4.1 обращалось внимание на необходимость круглых скобок в выражениях, содержащих оператор обращения к значению и точечный оператор. Аналогично необходимы круглые скобки вокруг части сложения указателей:
last = *ia + 4; // ok: last = 4, эквивалент ia[0] + 4
Этот код обращается к значению ia и добавляет 4 к полученному значению. Причины подобного поведения рассматриваются в разделе 4.1.2.
Как уже упоминалось, в большинстве мест, где используется имя массива, в действительности используется указатель на первый элемент этого массива. Одним из мест, где компилятор осуществляет это преобразование, является индексирование массива.
int ia[] = {0,2,4,6,8}; // массив из 5 элементов типа int
Рассмотрим выражение ia[0], использующее имя массива. При индексировании массива в действительности индексируется указатель на элемент в этом массиве.
int i = ia[2]; // ia преобразуется в указатель на первый элемент ia
// ia[2] выбирает элемент, на который указывает (ia + 2)
int *p = ia; // p указывает на первый элемент в массиве ia
i = *(p + 2); // эквивалент i = ia[2]
Оператор индексирования можно использовать для любого указателя, пока он указывает на элемент (или позицию после конца) в массиве.
int *p = &ia[2]; // p указывает на элемент с индексом 2
int j = p[1]; // p[1] - эквивалент *(p + 1),
// p[1] тот же элемент, что и ia[3]
int k = p[-2]; // p[-2] тот же элемент, что и ia[0]
Последний пример указывает на важное отличие между массивами и такими библиотечными типами, как vector и string, у которых есть операторы индексирования. Библиотечные типы требуют, чтобы используемый индекс был беззнаковым значением. Встроенный оператор индексирования этого не требует. Индекс, используемый со встроенным оператором индексирования, может быть отрицательным значением. Конечно, полученный адрес должен указывать на элемент (или позицию после конца) массива, на который указывает первоначальный указатель.
В отличие от индексов для векторов и строк, индекс встроенного массива не является беззнаковым.
Упражнение 3.34. С учетом, что указатели p1 и p2 указывают на элементы в том же массиве, что делает следующий код? Какие значения p1 или p2 делают этот код недопустимым?
p1 += p2 - p1;
Упражнение 3.35. Напишите программу, которая использует указатели для обнуления элементов массива.
Упражнение 3.36. Напишите программу, сравнивающую два массива на равенство. Напишите подобную программу для сравнения двух векторов.
3.5.4. Символьные строки в стиле С
Хотя язык С++ поддерживает строки в стиле С, использовать их в программах С++ не следует. Строки в стиле С — на удивление богатый источник разнообразных ошибок и наиболее распространенная причина проблем защиты.
Символьный строковый литерал — это экземпляр более общей конструкции, которую язык С++ унаследовал от языка С: символьной строки в стиле С (C-style character string). Строка в стиле С не является типом данных, скорее это соглашение о представлении и использовании символьных строк. Следующие этому соглашению строки хранятся в символьных массивах и являются строкой с завершающим нулевым символом (null-terminated string). Под завершающим нулевым символом подразумевается, что последний видимый символ в строке сопровождается нулевым символом ('\0'). Для манипулирования этими строками обычно используются указатели.
Стандартная библиотека языка С предоставляет набор функций, перечисленных в табл. 3.8, для работы со строками в стиле С. Эти функции определены в заголовке cstring, являющемся версией С++ заголовка языка С string.h.
Функции из табл. 3.8 не проверяют свои строковые параметры