Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

double* p2 = p1+7;

double* p3 = &p1[7];

if (p2 != p3) cout << "impossible!\n";

В основном это произошло по историческим причинам. Эти правила были разработаны для языка C несколько десяткой лет назад, и отменить их невозможно, не выбросив в мусорную корзину огромное количество программ. Частично это объясняется тем, что арифметика указателей обеспечивает определенное удобство в некоторых низкоуровневых приложениях, например в механизме управления памятью.

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

Имя массива относится ко всем элементам массива. Рассмотрим пример.

char ch[100];

Размер массива

ch
, т.е.
sizeof(ch)
, равен 100. Однако имя массива без видимых причин превращается в указатель.

char* p = ch;

Здесь указатель

p
инициализируется адресом
&ch[0]
, а размер
sizeof(p)
равен 4 (а не 100). Это свойство может быть полезным. Например, рассмотрим функцию
strlen
, подсчитывающую количество символов в массиве символов, завершающимся нулем.

int strlen(const char* p) // аналогична стандартной

// функции strlen

{

int count = 0;

while (*p) { ++count; ++p; }

return count;

}

Теперь можем вызвать ее как с аргументом

strlen(ch)
, так и с аргументом
strlen(&ch[0]
). Возможно, вы заметили, что такое обозначение дает очень небольшое преимущество, и мы с вами согласны. Одна из причин, по которым имена массивов могут превращаться в указатели, состоит в желании избежать передачи большого объема данных по значению. Рассмотрим пример.

int strlen(const char a[]) // аналогична стандартной

// функции strlen

{

int count = 0;

while (a[count]) { ++count; }

return count;

}

char lots [100000];

void f

{

int nchar = strlen(lots);

// ...

Наивно (но частично обоснованно) мы могли бы ожидать, что при выполнении этого вызова будут скопированы 100 тыс. символов, заданных как аргумент функции

strlen
, но этого не происходит. Вместо этого объявление аргумента
char p[]
рассматривается как эквивалент объявления
char* p
, а вызов
strlen(lots)
— как эквивалент вызова
strlen(&lots[0])
. Это предотвращает затратное копирование, но должно вас удивить. Почему вы должны удивиться? Да потому, что в любой другой ситуации при передаче объекта, если вы не потребуете явно, чтобы он передавался по ссылке (см. разделы 8.5.3–8.5.6), этот объект будет скопирован.

Обратите внимание на то, что указатель, образованный из имени массива, установлен на его первый элемент и не является переменной, т.е. ему ничего нельзя присвоить.

char ac[10];

ac = new char [20]; // ошибка: имени массива ничего присвоить нельзя

&ac[0] = new char [20]; // ошибка: значению указателя ничего

// присвоить нельзя

И на десерт — проблема, которую компилятор может перехватить!

Вследствие неявного превращения имени массива в указатель мы не можем даже скопировать массивы с помощью оператора присваивания.

int x[100];

int y[100];

// ...

x = y; // ошибка

int z[100] = y; // ошибка

Это логично, но неудобно. Если необходимо скопировать массив, вы должны написать более сложный код. Рассмотрим пример.

for (int i=0; i<100; ++i) x[i]=y[i]; // копируем 100 чисел типа int

memcpy(x,y,100*sizeof(int)); // копируем 100*sizeof(int) байт

copy(y,y+100, x); // копируем 100 чисел типа int

Поскольку в языке C нет векторов, в нем интенсивно используются массивы. Вследствие этого в огромном количестве программ, написанных на языке C++, используются массивы (подробнее об этом — в разделе 27.1.2). В частности, строки в стиле C (массивы символов, завершаемые нулем; эта тема рассматривается в разделе 27.5) распространены очень широко.

  • Читать дальше
  • 1
  • ...
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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