C++.Бархатный путь

       

Массив и константный указатель


Несмотря на некоторое сходство с константным указателем, массив является особым типом данных. В этом разделе мы рассмотрим основные отличия массива и константного указателя.

Прежде всего, рассмотрим варианты инициализации указателя:

char * const pcchVal_1 = chArray_2; char * const pcchVal_2 = new char[5]; char * const pcchVal_3 = (char *) malloc(5*sizeof(char));

Для инициализации последнего константного указателя был использован вызов функции malloc().

Каждый из этих операторов демонстрирует один из трёх возможных способов инициализации константного указателя: непосредственное присвоение значения, использование операции new, вызов функции. Операция new и функции распределения памяти, выделяют соответствующие участки памяти и возвращают начальный адрес выделенной области памяти. Ни один из этих способов не подходит для инициализации массива.

В свою очередь, при определении константных указателей не используются уже известные инициализаторы массивов с явным указанием размерности и списком инициализаторов.

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

int intArray[5]= {11,22,33,44,55}; int * const pciVal = new int[5];

К константным указателям и массивам применимы одни и те же методы навигации, связанные с использованием операции индексации:

intArray[-25] = 10; *(intArray + 25) = 10; pciVal[2] = 100; *(pciVal + 5) = 100;

А теперь применим операцию sizeof по отношению к проинициализированным указателям: cout "pciVal:" sizeof(pciVal) " intArray:" sizeof(intArray);

Для Borland C++ 4.5, операция sizeof покажет размер области памяти, занимаемой указателем (4 байта) и размер массива (размер элемента * размерность массива)==(10 байт). Операция sizeof различает указатели и имена массивов.

Кроме того, следующий тест также даёт различные результаты.

if (intArray == intArray) cout "Yes, массив." endl; else cout "No, массив." endl; if (pciVal == pciVal) cout "Yes, указатель. " endl; else cout "No, указатель." endl;


Результат выполнения:

Yes, массив. No, указатель.

Значение указателя, представляющего массив, совпадает с адресом первого элемента массива.

Значением указателя, проинициализированного с помощью выражения размещения, является адрес начала этой области. Сам указатель как объект обладает своим собственным адресом.

Интересно, что сравнение значения указателя с результатом выполнения операции взятия адреса не является абсолютно корректным с точки зрения соответствия типов. Операция взятия адреса возвращает лишь определённое значение адреса. И при этом после выполнения этой операции как бы ничего не известно о типе операнда, чей адрес определяли с помощью этой самой операции взятия адреса. Транслятор отслеживает это нарушение принципа соответствия типов и выдаёт предупреждение "Nonportable pointer comparison".

Поскольку это всего лишь предупреждение, выполнение процесса трансляции не прерывается и загрузочный модуль, построенный на основе этого программного кода, корректно выполняется. "Успокоить" транслятор можно с помощью операции явного преобразования типа, которая отключает контроль над типами:

if (intArray == (int *)intArray) cout "Yes"; else cout "No";


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