Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Пространства имен стандартной библиотеки.




Объекты стандартной библиотеки определены в пространстве имен std.Например, объявления стандартных средств ввода/вывода С в заголовочном файле <stdio.h>помещены в пространство имен следующим образом:

namespace std{

int feof (FILE *f);

}

using namespace std;

Если нежелательно присутствие неявно доступных имен, необходимо использовать заголовочный файл cstdio, где пространство имен std определено следующим образом:

namespace std{

int feof(FILE * f);

}

При этом доступ к именам пространтсва нужно осуществлять с указанием имени пространства имен явным образом:

std::feof(f);

 

Тема 1.24

Директивы препроцессора

 

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

Препроцессор может обрабатывать не только тексты программ на языке С++, а также произвольные тексты.

Стадии препроцессорной обработки

Препроцессорная обработка включает несколько последовательно выполняемых стадий (конкретная реализация может объединять несколько стадий в одну):

1. все системно-зависимые обозначения (например, индикатор конца строки) перекодируются в стандартные коды,

2. каждая пара из символов ‘\’ и “конец строки” вместе с пробелами между ними убираются, и тем самым соседние строки конкатенируются, т.е. соединяются в одну строку (далее каждая полученная таким образом строка обрабатывается препроцессором отдельно),

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

4. выполняются директивы препроцессора и производятся макроподстановки,

5. escape-последовательности в символьных константах и строках (например ‘\n’ или ‘\xF2’'), заменяются соответствующими числовыми кодами,

6. смежные символьные константы и строки кон­катенируются,

7. каждая препроцессорная лексема преобразуется в текст на языке С++.

К препроцесорным лексемам (лексемам препроцессора, preprocessing token) относятся:

· символьные константы,

· строковые константы,

· имена заголовочных файлов,

· идентификаторы,

· знаки операций,

· препроцессорные числа,

· знаки препинания,

· другие символы, отличные от пробела.

Директивы препроцессора

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

На стадии обработки директив препроцессора в зависимости от типа директивы могут выполняться следующие действия:

· замена идентификаторов определенной последовательностью символов,

· включение в программу текстов из заголовочных файлов,

· исключение из программы отдельных частей ее текста (условная компиляция),

· макроподстановка, т.е. замена обозначения параметризованным текстом, формируемым препроцессором с учетом конкретных параметров.

Обобщенный формат директивы препроцессора:

#имя_директивы лексемы_препроцессора

Каждая директива должна располагаться в отдельной строке. До и после символа ‘#’, до, после и между лексема­ми препроцессора могут содержаться пробелы.

Окончанием препроцессорной директивы служит конец текстовой строки, при наличии символа ‘\’, обозначающего перенос строки - конец следую­щей строки текста.

Определены следующие препроцессорные директивы: #define, #undef, #include, #if, #ifdef, #ifndef, #else, #endif, #elif, #line, #error, #pragma, #.

Кроме препроцессорных директив имеются три препроцессорные операции, используемые совместно с директивой #define: #, ##, defined.

Директива #define

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

Также с помощью директивы #define определяются символические константы, управляющие условной компиляцией, и используемые директивами #ifdef и #ifndef.

Директива имеет несколько модификаций:

· макроопределение без параметров,

· макроопределение с параметрами,

· определение идентификатора, управляющего условной компиляцией.

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

Макроопределение без параметров имеет вид:

#define идентификатор строка_замещения

Оно задает препроцессорный макрос без параметров. Идентификатор задает имя макроса, которое будет использоваться для обращения к нему.

В результате работы препроцессора все вхождения указанного идентификатора в тексте программы заменяются на символьную последовательность, задаваемую строкой замещения. Сим­волы пробелов, помещенные в начале и в конце строки замещения, в подстановке не используются. Данный процесс называется макровызовом (вызовом макроса). Выполненные директивы #define из текста исключаются.

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

Пример:

Исходный текст Результат препроцессорной обработки

#define begin {

#define end }

void main() void main()

begin {

операторы операторы

end }

В исходном тексте программы в качестве операторных скобок используются идентификаторы begin, end.Препроцессор заменяет все вхождения данных идентификаторов скобками { и }.

Если строка замещения является слишком длинной, она может быть перенесена на следующую строку. Это можно осуществить, поместив символ ‘\’ в конце продолжаемой строки. В ходе второй стадии препроцессорной обработки этот символ вместе с последующим символом конца строки будет удален из текста программы.

Пример:

#define STRING "\n Game Over! - \

Игра закончена!"

printf (STRING);

На экран будет выведено:

Game Over! - Игра закончена!

В примере имя макроса записано прописными буквами. Данный прием позволяет зрительно отличать имена макросов от имен переменных и функций.

Действие макроподстановок, выполняемых согласно с директивой #define, имеет ряд ограничений. Замены не выполняются внутри:

· комментариев (строк, ограниченных символами /* и */ или записанных после знака //),

· символьных констант (символов, ограничен­ных апострофами '),

· строковых констант (строк, ограниченных двойными кавычками "),

· внутри идентификаторов (часть идентификатора не может быть заменена).

Пример:

#define n 24

char с = '\n'; // c - cимвольная константа, \n - escape-последовательность

c = ‘n’ > ‘\n’?'\n':'\n'

int k = n;

В ходе препроцессорной обработки данного текста замена идентификатора n на число 24 будет выполнена только один раз в последнем определении, которое примет вид:

int k=24;

Все остальные вхождения символа n в составе строковых констант препроцессором будут проигнорированы.

В строке замещения символы /*, */, //, ', " могут присутствовать (например, как в строке замещения макроса STRING).

Строку замещения, связанную с конкретным препроцессорным идентификатором, можно сменить, приписав уже определенному идентификатору новое значение другой командой #define:

#define M 16 // идентификатор М определен как 16

#define M ‘С’ // идентификатор М определен как символьная константа ‘С’

#define M “С” // идентификатор М определен как строковая константа

Однако при таких сменах значений препроцессорного иден­тификатора компилятор выдает предупреждающее сообщение на каждую следующую директиву #define:

Warning..: Redefinition of 'M' is not identical

Цепочка подстановок

В рассмотренных выше примерах строка замещения представляла собой некоторую символьную константу. В более общем случае строка замещения является выражением. В качестве отдельной лексемы в ней может содержаться макрос, ранее определенный другой директивой #define.Таким образом, препроцессор выполняет цепочку последовательных подстано­вок.

Пример: Определение диапазона возможных значений любой целой переменной типа int.

#include <limits.h>

#define RANGE ((INT_MAX) - (INT_MIN) +1)

/*RANGE - диапазон значений для int */

int RANGE_T = RANGE/8;

При работе препроцессора сначала выполняется директива #include <limits.h> - в текст программы вставляется текст из файла limits.h.

В данном файле определены константы INT_MAX, INT_MIN, указывающие предельное максимальное и минимальное значение целых величин соответственно. Таким образом, программа принимает вид:

#define INT_MAX 32767

#define INT_MIN -32768

#define RANGE ((INT_MAX) - (INT_MIN) + 1)

/*RANGE - диапазон значений для int*/

int RANGE_T = RANGE/8;

Директива #includeв тексте программы заменилась на соответствующий текст (значения констант могут различаться в зависимости от разрядности ЭВМ).

Далее препроцессор выполняет подстановки в соответствии с двумя первыми директивами #define и программа принимает вид:

#define RANGE ((32767) - (-32768) + 1)

/*RANGE - диапазон Значений для int*/

int RANGE_T = RANGE/8;

В результате выполнения подстановок изменилась строка замещения макроса RANGE в последней директиве #define. После выполнения данной директивы текст программы примет вид:

/*RANGE - диапазон значений для int*/

int RANGE_T = ((32767)-(-32768)+1)/8;

Теперь все директивы #define удалены из текста.

Подстановка строки замещения вместо имени макроса RANGE была выполнена в выражении RANGE/8. Согласно рассмотренным ранее ограничениям не произошло подстановки внутри комментария, а также остался без изменений идентификатор RANGE_T.

Параметризованное макороопределение

Недостатком макроопределения без параметров является то, что замещения фиксиро­вана. Большие возможности предоставляет макроопределение с параметрами:

#define идентификатор(параметры) строка_замещения

параметры - список идентификаторов, разделенных запятыми. Между именем макроса и скобкой не должно быть пробелов.

Для макровызова использу­ется конструкция вида:

идентификатор (аргументы)

аргументы – список препроцессорных лексем, разделенных запятыми.

Пример:

Макроопределение

#define MAX(x,y) ((x) > (y)? (x): (y))

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

Аргументы макровызова используются при макроподстановке. Например, макровызов

у = MAX(suml, sum2);

он будет заменен на

у = ((suml)>(sum2)?(suml):(sum2));

Отсутствие круглых скобок может привести к неправильному порядку вычисле­ния, поскольку препроцессор не оценивает строку замещения текст с точки зрения синтаксиса.

Пример:

Если определен макрос

#define sqr(x) (x*x)

то макровызов sqr(y+l) будет заменен выражением sqr(у+1*у+1).

Последовательные подстановки, выполняемые в строке замещения, не действуют на параметры макроса, т.е. аргумент макроса не может быть выражением, содержащим переменные, ранее определенные другой директивой #define.





Поделиться с друзьями:


Дата добавления: 2016-11-12; Мы поможем в написании ваших работ!; просмотров: 513 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Начинать всегда стоит с того, что сеет сомнения. © Борис Стругацкий
==> читать все изречения...

2300 - | 2053 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.009 с.