4.11. Препроцессор языка “C”.
В языке “с” предусмотрены определенные расширения языка с помощью простого макропредпроцессора. одним из самых распространенных таких расширений, которое мы уже использовали, является конструкция #DEFINE; другим расширением является возможность включать во время компиляции содержимое других файлов.
4.11.1. Включение файлов
Для облегчения работы с наборами конструкций #DEFINE и описаний (среди прочих средств) в языке “с” предусмотрена возможность включения файлов. Любая строка вида
#INCLUDE “FILENAME” заменяется содержимым файла с именем FILENAME. (Кавычки обязательны). Часто одна или две строки такого вида появляются в начале каждого исходного файла, для того чтобы включить общие конструкции #DEFINE и описания EXTERN для глобальных переменных. Допускается вложенность конструкций #INCLUDE.
Конструкция #INCLUDE является предпочтительным способом связи описаний в больших программах. Этот способ гарантирует, что все исходные файлы будут снабжены одинаковыми определениями и описаниями переменных, и, следовательно, исключает особенно неприятный сорт ошибок. Естественно, когда какой-TO включаемый файл изменяется, все зависящие от него файлы должны быть перекомпилированы.
4.11.2. Макроподстановка
Определение вида #DEFINE TES 1 приводит к макроподстановке самого простого вида - замене имени на строку символов. Имена в #DEFINE имеют ту же самую форму, что и идентификаторы в “с”; заменяющий текст совершенно произволен. Нормально заменяющим текстом является остальная часть строки; длинное определение можно продолжить, поместив в конец продолжаемой строки. “Область действия” имени, определенного в #DEFINE, простирается от точки определения до конца исходного файла. имена могут быть переопределены, и определения могут использовать определения, сделанные ранее. Внутри заключенных в кавычки строк подстановки не производятся, так что если, например, YES - определенное имя, то в PRINTF(“YES”) не будет сделано никакой подстановки.
Так как реализация #DEFINE является частью работы маKропредпроцессора, а не собственно компилятора, имеется очень мало грамматических ограничений на то, что может быть определено. Так, например, любители алгола могут объявить
#DEFINE THEN #DEFINE BEGIN { #DEFINE END ;}
и затем написать IF (I > 0) THEN BEGIN A = 1;
B = 2 END Имеется также возможность определения макроса с аргументами, так что заменяющий текст будет зависеть от вида обращения к макросу. Определим, например, макрос с именем MAX следующим образом:
#DEFINE MAX(A, B) ((A) > (B) ? (A) : (B)) когда строка X = MAX(P+Q, R+S);
будет заменена строкой X = ((P+Q) > (R+S) ? (P+Q) : (R+S));
Такая возможность обеспечивает “функцию максимума”, которая расширяется в последовательный код, а не в обращение к функции. При правильном обращении с аргументами такой макрос будет работать с любыми типами данных; здесь нет необходимости в различных видах MAX для данных разных типов, как это было бы с функциями.
Конечно, если вы тщательно рассмотрите приведенное выше расширение MAX, вы заметите определенные недостатки. Выражения вычисляются дважды; это плохо, если они влекут за собой побочные эффекты, вызванные, например, обращениями к функциям или использованием операций увеличения. Нужно позаботиться о правильном использовании круглых скобок, чтобы гарантировать сохранение требуемого порядка вычислений. (Рассмотрите макрос
#DEFINE SQUARE(X) X * X при обращении к ней, как SQUARE(Z+1)). Здесь возникают даже некоторые чисто лексические проблемы: между именем макро и левой круглой скобкой, открывающей список ее аргументов, не должно быть никаких пробелов.
Тем не менее аппарат макросов является весьма ценным.
Один практический пример дает описываемая в главе 7 стандартная библиотека ввода-вывода, в которой GETCHAR и PUTCHAR определены как макросы (очевидно PUTCHAR должна иметь аргумент), что позволяет избежать затрат на обращение к функции при обработке каждого символа.
Другие возможности макропроцессора описаны в приложении А.
Упражнение 4-9.
Определите макрос SWAP(X, Y), который обменивает значениями два своих аргумента типа INT. (В этом случае поможет блочная структура).
98
5.Указатели и массивы Указатель - это переменная, содержащая адрес другой переменной. указатели очень широко используются в языке “C”.
Это происходит отчасти потому, что иногда они дают единственную возможность выразить нужное действие, а отчасти потому, что они обычно ведут к более компактным и эффективным программам, чем те, которые могут быть получены другими способами.
Указатели обычно смешивают в одну кучу с операторами GOTO, характеризуя их как чудесный способ написания программ, которые невозможно понять. Это безусловно спрAведливо, если указатели используются беззаботно; очень просто ввести указатели, которые указывают на что-то совершенно неожиданное. Однако, при определенной дисциплине, использование указателей помогает достичь ясности и простоты. Именно этот аспект мы попытаемся здесь проиллюстрировать.
... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...
... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...
... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...
... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...
0 комментариев