Страница 68 из 82
Массив и константный указатель Несмотря на некоторое сходство с константным указателем, массив является особым типом данных. В этом разделе мы рассмотрим основные отличия массива и константного указателя. Прежде всего, рассмотрим варианты инициализации указателя: 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"; |