Язык программирования C++ от Страуструпа

       

Указатели и массивы


Массив можно описать так:

char v [ 10 ]; // массив из 10 символов

Описание указателя имеет такой вид:

char * p; // указатель на символ

Здесь [] означает "массив из", а символ * означает "указатель на". Значение нижней границы индекса для всех массивов равно нулю, поэтому v имеет 10 элементов: v [ 0 ] ... v [ 9 ]. Переменная типа указатель может содержать адрес объекта соответствующего типа:

p = & v [ 3 ]; // p указывает на 4-й элемент массива v

Унарная операция & означает взятие адреса.


Указатели и массивы в языке Си++ тесно связаны. Имя массива можно использовать как указатель на его первый элемент, поэтому пример с массивом alpha  можно записать так:

int main()

{

  char alpha[] = "abcdefghijklmnopqrstuvwxyz";

  char* p = alpha;



  char ch;

  while (ch = *p++)

     cout << ch << " = " << int (ch)

          << " = 0" << oct(ch) << '\n';

}

Можно также задать описание p следующим образом:

char* p = &alpha[0];

Эта эквивалентность широко используется при вызовах функций с параметром-массивом, который всегда передается как указатель на его первый элемент. Таким образом, в следующем примере в обоих вызовах strlen передается одно и то же значение:

void f()

{

  extern "C" int strlen(const char*);  // из <string.h>

  char v[] = "Annemarie";

  char* p = v;

  strlen(p);

  strlen(v);

}

Но в том и загвоэдка, что обойти это нельзя: не существует способа так

описать функцию, чтобы при ее вызове массив v копировался ($$4.6.3).

Результат применения к указателям арифметических операций +, -, ++ или -- зависит от типа указуемых объектов. Если такая операция применяется к указателю p типа T*, то считается, что p указывает на массив объектов типа T. Тогда p+1 обозначает следующий элемент этого массива, а p-1 - предыдущий элемент. Отсюда следует, что значение (адрес) p+1 будет на sizeof(T) байтов больше, чем значение p. Поэтому в следующей программе

main()

{

  char cv[10];

  int iv[10];

  char* pc = cv;

  int* pi = iv;

  cout << "char* " << long(pc+1)-long(pc) << '\n';

  cout << "int*  " << long(pi+1)-long(pi) << '\n';

}

с учетом того, что на машине автора (Maccintosh) символ занимает один байт,

а целое - четыре байта, получим:

char* 1

int*  4

Перед вычитанием указатели были явной операцией преобразованы к типу long ($$3.2.5). Он использовался для преобразования вместо "очевидного" типа int, поскольку в некоторых реализациях языка С++ указатель может не поместиться в тип int (т.е. sizeof(int)<sizeof(char*)).



Содержание раздела