- •Алфавиты и типы данных. Целые и плавающие типы.
- •Выражение присваивания. Арифметические операции с целыми и плавающими переменными.
- •Логические операции, операции автоувеличения и автоуменьшения, тернарная операция.
- •Составной оператор. Условный оператор.
- •Оператор switch – case. Оператор безусловного перехода, break, continue.
- •Операторы цикла. Оператор безусловного перехода, break, continue.
- •Указатели. Указатели и массивы. Адресная арифметика.
- •Символьные массивы и строки. Указатели и многомерные массивы.
- •9. Операции для работы с динамической памятью.
- •10. Объявления и определения. Область существования имени.
- •11. Область видимости имён. Классы памяти.
- •12. Объявления объектов и типов. Синоним имени типа.
- •13. Правила преобразования стандартных типов. Неявные преобразования стандартных базовых типов. Преобразования производных стандартных типов.
- •14. Функции. Передача аргументов. Указатели на функции.
- •15. Ссылки. Передача аргументов в функции по ссылке.
- •16. Функции. Аргументы по умолчанию и переопределение функций.
- •17. Шаблоны функций.
- •Перечисления
- •Классы. Конструкторы и деструкторы.
- •Статические члены класса
- •Указатель this. Статические функции-члены.
- •Указатели на члены класса
- •Конструктор копирования и операция присваивания
- •Дружественные (привилегированные) функции
- •Производные классы. Построение. Защищенные классы. Производные классы Построение производного класса
- •Защищенные члены класса
- •Управление уровнем доступа к членам класса
- •19.4. Последовательность вызова конструктора и деструктора при построении производного класса на основе одного базового
- •Преобразования типов. Связь с наследованием. Преобразование типов
- •Раннее и позднее связывание (полиморфизм). Виртуальные функции. Полиморфизм
- •Раннее и позднее связывание
- •Виртуальные функции
12. Объявления объектов и типов. Синоним имени типа.
При объявлениях можно использовать одновременно более одного модификатора (это * [ ] и ( ) ). Это даёт возможность создавать бесконечное множество сложных описателей типов. В то же время, некоторые комбинации недопустимы:
элементами массива не могут быть функции;
функции не могут возвращать массив или функцию.
При интерпретации сложных описателей квадратные и круглые скобки (справа от идентификатора) имеют приоритет перед * (слева от идентификатора). Квадратные или круглые скобки имеют один и тот же приоритет.
Спецификатор типа рассматривается на последнем шаге. Можно использовать круглые скобки, чтобы изменить порядок интерпретации на необходимый. Для правильной интерпретации сложных описателей можно придерживаться следующего правила ("изнутри - наружу").
Начать с идентификатора и посмотреть вправо, есть ли квадратные или круглые скобки.
Если они есть, то проинтерпретировать эту часть описателя и затем посмотреть налево в поиске *.
Если на любой стадии справа встретится закрывающая круглая скобка, то вначале необходимо применить все эти правила внутри круглых скобок, а затем продолжить интерпретацию.
Интерпретировать спецификатор типа.
Например, при использовании конструкции
int *(*array[10]) ( );
объявляется имя array как массив из 10 указателей на функцию без аргументов, возвращающую указатель на целое значение.
В некоторых конструкторах языка явно используются имена типов (операции sizeof, new, cast). Имя типа - это просто объявление объекта такого типа, в котором опущено имя самого объекта.
Примеры имён типов:
int - целое
double - плавающее с двойной точностью
int * - указатель на целое
int * [10] - массив указателей на целое
int(*)[10] - указатель на массив на 10 целых
int * (void) - функция без аргументов, возвращающая указатель на целое.
int (*) (void) - указатель на функцию без аргументов, возвращающую результат целого типа.
Синоним имени типа строится при помощи ключевого слова typedef. Выражение, в котором присутствует это ключевое слово, является описанием некоторого имени. Наличие слова typedef говорит о том, что объявляемый идентификатор становится не именем объекта некоторого типа, а синонимом имени этого типа.
int INTEGER; // INTEGER - имя переменной типа int
typedef int INT; // INT - синоним типа int
typedef unsigned size_t;
typedef char string [255];
typedef void (*FPTR) (int);
Последние две строки определяют string как синоним типа "строка из 255 символов", а FPTR - синоним типа "указатель на функцию, имеющую один аргумент типа int и не возвращающую никакого результата."
После объявления с помощью typedef новое имя становится полноценным именем типа:
string array; // array - массив из 255 символов
FPTR func_pointer; // void (*func_pointer)(int);
typedef string STRING;
Использование typedef может упростить понимание сложных имен типов. Так, тип int (*(void))[ ] можно построить так:
typedef int intarray[]; // тип "массив целых"
typedef intarray * ptrtointarray; //тип указателя на массив целых
typedef ptrtointarray TYPE (void);
Теперь имя TYPE можно использовать, например, в прототипах:
double fun (int, int, TYPE);
