Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
62
Добавлен:
02.05.2014
Размер:
543.23 Кб
Скачать

Билет 27

1. Преобразования символов

Символ или короткое целое могут использоваться, если мо­жет использоваться целое. Во всех случаях значение преобразуется к целому. Преобразование короткого целого к длинному всегда включает в себя знаковое расширение; целые являются величинами со знаком. Содержат символы знаковый раз­ряд или нет, является машинно зависимым, см. #2.6. Более яв­ный тип unsigned char ограничивает изменение значения от 0 до машинно зависимого максимума.

В машинах, где символы рассматриваются как имеющие знак (знаковые), символы множества кода ASCII являются положитель­ными. Однако, символьная константа, заданная восьмеричной escпоследовательностью подвергается знаковому расширению и может стать отрицательным числом; так например, '\377' имеет значение -1.

Когда длинное целое преобразуется в короткое или в char, оно урезается влево; избыточные биты просто теряются.

Некоторые макросы выполняют проверку символов и преобра- зования:

SALPHA(C) не 0, если "C" алфавитный символ, 0 - если нет. SUPPER(C) Не 0, если "C" буква верхнего регистра, 0 - если нет. SLOWER(C) Не 0, если "C" буква нижнего регистра, 0 - если нет. SDIGIT(C) Не 0, если "C" цифра, 0 - если нет. SSPACL(C) Не 0, если "C" пробел, табуляция или новая строка, 0 - если нет. OUPPER(C) Преобразует "C" в букву верхнего регистра. OLOWER(C) Преобразует "C" в букву нижнего регистра.

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

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

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

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";

Соседние файлы в папке Програмки на C++