Второе отличие между указателями и индексами массива состоит в том, что 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
Если есть указатели на массивы, можно предположить, что существуют и массивы указателей. Именно их мы сейчас и рассмотрим.
Поскольку массив может содержать данные любого типа, он может состоять и из указателей. Массив указателей объявляется так:
int* pInts[ 10 ] ;
Таким образом, элемент pInts[ 0 ] является указателем на переменную типа int. Следовательно, приведённый ниже код корректен:
void fn( )
{
int n1 ;
int* pInts[ 3 ] ;
pInts[ 0 ] = &n1 ;
*pInts[ 0 ] = 1 ;
}
Как и этот:
void fn( )
{
int n1 , n2 , n3 ;
int* pInts[ 3 ] = { &n1 ,&n2 ,&n3 } ;
for ( int i = 0 ; i < 3 ; i++ )
{
*pInts[ i ] = 0 ;
}
}
И даже этот:
void fn( )
{
int n1 , n2 , n3 ;
int* pInts[ 3 ] = { ( new int ) ,
( new int ) ,
( new int ) } ;
for ( int i = 0 ; i < 3 ; i++ )
{
*pInts[ i ] = 0 ;
}
}
В последнем варианте память под переменные выделяется из кучи.
Массивы указателей чаще всего используются для работы с массивами строк. Приведённые далее примеры показывают, почему это удобно.
Использование массивов строк...124
Допустим, мне понадобилась функция, возвращающая название месяца по его номеру. Например, если этой функции передать число 1, она вернёт название первого месяца — "Январь". Номер месяца будет считаться неправильным, если он окажется меньше 1 или больше 12.
_________________
124 стр. Часть 2. Становимся функциональными программистами
Эту функцию можно написать следующим образом:
/* int2month( ) — возвращает название месяца */
char* int2month( int nMonth )
{
char* pszReturnValue ;
switch( nMonth )
{
case 1 : pszReturnValue = "Январь" ;
break ;
case 2 : pszReturnValue = "Февраль" ;
break ;
case 3 : pszReturnValue = "Март" ;
break ;
/* и так далее... */
default : pszReturnValue = "Неверный номер месяца"
}
return pszReturnValue ;
}
«Оператор switch( ) действует так же, как совокупность операторов if.»
[Помни!]
Эту задачу можно решить более элегантно, использовав номер месяца как индекс в массиве указателей, представляющих названия месяцев. Тогда программа приобретёт такой вид:
/* int2month( ) — возвращает название месяца */
char* int2month( int nMonth )
{
/* проверка правильности номера месяца */
if ( nMonth < 1 || nMonth > 12 )
{
return "invalid" ;
}
/* nMonth имеет корректное значение */
/* Вернём имя месяца */
char* pszMonths[ ] = { "Ошибка" ,
"Январь" ,
"Февраль" ,
"Март" ,
"Апрель" ,
"Май" ,
"Июнь" ,
"Июль" ,
"Август" ,
"Сентябрь" ,
"Октябрь" ,
"Ноябрь" ,
"Декабрь" } ;
return pszMonths[ nMonth ] ;
}