Именно тогда и зародилась традиция писать компактные и эффективные, правда, подчас несколько загадочные на вид программы на С++, и с тех пор никто не хочет возвращаться к индексам.

«Не надейтесь, что, написав сложное и запутанное выражение на С++, вы сэкономите несколько машинных команд. В С++ нет прямой связи между количеством команд в исходном и конечном коде.»
[ Советы ]
Операции с указателями других типов...122
Нетрудно сообразить, что szTarget+n указывает на элемент szTarget[ n ] , если szTarget является массивом однобайтовых значений. Если szTarget начинается по адресу 0x100 , то шестой элемент массива будет находиться по адресу 0x105.
Однако положение элемента в массиве становится не столь очевидным, если массив состоит из элементов типа int , которые занимают по четыре байта каждый. Если первый элемент такого массива находится по адресу 0x100 , то шестой будет находиться по адресу 0x114( 0x100 + ( 5 * 4 ) = 0x114 ) .
Но, к счастью для нас, выражение вида array + n будет всегда указывать на элемент array[ n ] , независимо от размера элемента, поскольку в таком выражении С++ самостоятельно учитывает длину элемента.
И вновь обратимся за аналогией к моему дому. Третий дом от 123 Main Street будет иметь адрес 126 Main Street , независимо от размеров стоящих на Main Street домов.
Отличия между указателями и массивами...122
В использовании массива и указателя есть несколько отличий. Во-первых, объявление массива вызывает выделение памяти для всего массива, тогда как объявление указателя не требует выделения памяти для массива.
void arrayPointer( )
{
/* Выделение памяти для 128 символов */
char charArray[ 128 ] ;
/* Выделение памяти для указателя, но не для объекта, на который он указывает */
char* pArray ;
}
_________________
122 стр. Часть 2. Становимся функциональными программистами
В этом примере для charArray выделяется 128 байт, а для pArray — четыре, ровно столько, сколько необходимо для хранения указателя. Приведённая ниже функция работать не будет.
void arrayVsPointer( )
{
/* Этот фрагмент будет работать нормально */
char charArray[ 128 ] ;
charArray[ 10 ] = '0' ;
*( charArray + 10 ) = '0' ;
/* Этот фрагмент не будет работать так, как надо */
char* pArray ;
pArray[ 10 ] = '0' ;
*( pArray + 10 ) = '0' ;
}
Выражения charArray[ 10 ] и *( charArray + 10 ) с позиции компилятора эквивалентны и вполне законны. Те же выражения с использованием pArray являются бессмысленными. Несмотря на то что для С++ они являются законными, pArray не инициализирован как указатель на массив, а значит, память была выделена только для указателя. Таким образом, рАггау[ 10 ] и *( рАггау + 10 ) указывают на неизвестные и непредсказуемые значения.

«Неправильно инициализированные указатели обычно вызывают ошибкунарушения сегмента (segment violation ). Эту ошибку вы иногда встречаете в повседневной работе со своими любимыми приложениями в своей любимой ( а может, и не очень ) операционной системе.»
[ Советы ]
Второе отличие между указателями и индексами массива состоит в том, что charArray — константа, тогда как pArray — нет. Приведённый ниже цикл for , который должен инициализировать значения элементов массива, тоже не будет работать.
void arrayVsPointer( )
{
char charArray[ 10 ] ;
for ( int i = 0 ; i < 10 ; i++ )
{
*charArray = '\0' ; /* Эта строка имеет смысл... */
charArray++ ; /* ... а эта нет */
}
}
Выражение charArray++ имеет не больше смысла, чем 10++. Правильно следует написать так:
void arrayVsPointer( )
{
char charArray[ 10 ] ;
char* pArray = charArray ;
for ( int i = 0 ; i < 10 ; i++ )
{
*pArray = '\0' ; /* Этот вариант будет работать так, как надо */
pArray++ ;
}
}
_________________
123 стр. Глава 9. Второе знакомство с указателями
►Объявление и использование массивов указателей...124
Если есть указатели на массивы, можно предположить, что существуют и массивы указателей. Именно их мы сейчас и рассмотрим.
Поскольку массив может содержать данные любого типа, он может состоять и из указателей. Массив указателей объявляется так:
Читать дальше