|
Программирование >> Структурное программирование
17.3. Директива препроцессора #define: символические константы Директива препроцессора #define создает символические константы, обозначаемые идентификаторами, и макросы - операции, обозначаемые символьными строками. Формат директивы препроцессора #define следующий tdefine идентификатор замещающий текст После появления этой строки в файле все встретившиеся далее в тексте программы имена, совпавшие с элементом директивы идентификатор, будут автоматически заменены на указанный в директиве замещающий текст прежде, чем начнется компиляция программы. Например, после задания директивы tdefine PI 3.14159 все последующие вхождения в текст программы символической константы PI будут заменены на численную константу 3.14159. Символические константы дают возможность программисту присвоить константе имя и использовать его далее в программе. Если возникнет необходимость изменить значение константы во всей программе, для этого достаточно будет внести только одно изменение в директиву препроцессора #define и перекомпилировать программу; значение 17.2. Директива препроцессора #include Директива препроцессора #include уже использовалась в тексте этой книги. Директива #include применяется для включения копии указанного в директиве файла в то месте, где находится эта директива. Существуют две формы директивы #include: tinclude <имя файла> tinclude имя файла Различие между ними заключается в методе поиска препроцессором включаемого файла. Если имя файла заключено в угловые скобки (< и >), как это делается для включения заголовочных файлов стандартной библиотеки, то последовательность поиска препроцессором заданного файла в каталогах определяется используемой системой программирования; обычно просматривается заранее установленный список каталогов. Если имя файла заключено в кавычки, препроцессор сначала ищет файл в том каталоге, где находится компилируемый файл, а затем продолжает поиск тем же способом, что и при угловых скобках. Такой формой обычно пользуются для включения заголовочных файлов, определяемых программистом. Директива #include обычно используется для включения стандартных заголовочных файлов, таких, как iostream.h и iomanip.h. Директива #include используется также при работе с программами, состоящими из нескольких исходных файлов, которые должны компилироваться вместе. Заголовочные файлы содержат объявления и определения, общие для различных программных файлов, и поэтому часто создаются и включаются в файлы программ. В качестве таких объявлений и определений выступают классы, структуры, объединения, перечислимые типы и прототипы функций. константы будет изменено по всей программе автоматически. Отметьте: все, что находится справа от имени символической константы., является замещающим ее текстом. Например, после выполнения директивы #define PI =3.14159 препроцессор заменит все имена PI на текст =3.14159. Многие логические и синтаксические ошибки возникают по причине непонимания этого правила. Переопределение значения символической константы является также, обычным источником ошибок. Заметим, что в 0++ отдается предпочтение использованию именованных переменных типа const, а не символических констант. Константные переменные являются данными определенного типа и их имена видны отладчику. А если используется символическая константа, то после того, как символическая константа была заменена на соответствуюш;ий текст, только этот текст и будет виден отладчику. Недостатком переменных типа const является то, что им требуется память в объеме, соответствуюш;ем их типу, для хранения своего значения, тогда как для символических констант не требуется никакой дополнительной памяти. Хороший стиль программирования 17.1 Использование ясных по смыслу имен для символических констант улучшает пони -мание текста программы, делает текст самодокументируемым. 17.4. Директива препроцессора #define: макросы Макрос, определяемый директивой препроцессора #define, это символическое имя некоторых операций. Как и в случае символических констант, идентификатор макроса заменяется на замещаюш;ий текст до начала компиляции программы. Макросы могут быть определены с параметрами или без них. Макросы без параметров обрабатываются подобно символическим константам. Если макрос имеет параметры, то сначала в замеш;ающий текст подставляются значения параметров, а затем уже этот расширенный макрос подставляется в текст вместо идентификатора макроса и списка его параметров. Рассмотрим следуюш;ий макрос с одним параметром для расчета площади круга #define CIRCLE AREA(х) ( PI * (х) * (х) ) Везде в файле, где появится идентификатор CIRCLE AREA(x), значение аргумента х будет использовано для замены х в замещающем тексте, символическая константа PI будет заменена ее значением (определенным выше) и этот расширенный текст макроса будет использован для замещения. Например, оператор с макросом в тексте программы area = CIRCLE AREA{4); примет вид: area = ( 3.14159 * (4) * (4) ) ; Поскольку это выражение состоит только из констант, его значение будет вычислено во время компиляции и полученный результат будет присвоен переменной area во время выполнения программы. Круглые скобки вокруг каждого включения параметра х в тексте макроса и вокруг всего выражения применяются для того, чтобы обеспечить соответствующий порядок вычис- Вычисления, выполняемые макросом CIRCLE AREA, можно выполнять при помощи функции. Функция circle Area double circleArea(double x) ( return 3.14159 * x * x; } выполняет те же вычисления, что и макрос CIRCLE AREA. Недостатком использования этой функции является то, что на ее вызов должны быть затрачены некоторые ресурсы. Преимущества использования макроса CIR-CLE AREA состоят в том, что вычисления, выполняемые макросом, непосредственно помещаются в текст программы и не приводят к дополнительным накладным расходам, связанным с вызовом функции; при этом текст программы остается легко читаемым, потому что имя CIRCLE AREA говорит само за себя. Недостаток этого макроса в том, что значение аргумента вычисляется дважды. И конечно, макрос будет расширяться при каждом своем появлении в тексте программы. Если макрос большой, то это приводит к увеличению размера программы. Таким образом, нужно искать компромисс между быстродействием и размером программы (если у вас маленький диск). Заметим, что предпочтительнее использовать встраиваемые inline функции (см. главу 3), которые обеспечивают эффективность макросов и преимущества функций при разработке программного обеспечения. Совет по повышению эффективности 17.1 Макросы могут использоваться для замены вызовов функций на встраиваемый в программу код. Это устраняет накладные расходы по вызову функции. Но предпочтительнее все же использовать встраиваемые функции. лений в том случае, когда аргументом макроса является выражение. Например, при раскрытии макроса в операторе area = CIRCLE AREA(с + 2); оператор примет следующий вид: area = ( 3.14159 * (с + 2) * (с + 2) ); И вычисления будут выполняться правильно, потому что скобки обеспечили правильную последовательность вычислений. Если в определении макроса опустить все круглые скобки, то после расширения макроса рассматриваемый оператор будет иметь следующий вид: area = 3.14159 * с + 2 * с + 2; С учетом приоритетов операций, вычисление значения выражения будет сделано в следующем порядке area = (3.14159 * с) + (2 * с) + 2; И будет получен неверный результат. Типичная ошибка программирования 17.1 Если параметры макроса в выражении для подстановки не заключены в круглые скобки, то при подстановке могут возникнуть ошибки последовательности вычислений.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |