Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 4 из 4
  1. #1
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±

    Препроцессор

    Введение

    Препроцессор, как утверждает Википедия – это компьютерная программа, принимающая данные на входе и выдающая данные, предназначенные для входа другой программы (например, компилятора). Чаще всего он применяется для автоматизации какого-либо процесса в программировании, например, подсчёта переменных и т.п. В Pawn препроцессор используется непосредственно для формирования какого-то структурированного кода, анализа чего-либо и т.д.

    Определения и их эквиваленты

    Определения (в данном случае имеется в виду object-like macro) – это константы, которые заменяются значениями в момент прекомпиляции. Они имеют глобальную зону видимости.
    PHP код:
    #define SOME_CONSTANT (0xFFFFFFFF) 
    Эквивалент определений – оператор const. Есть два основных отличия: оператор может иметь локальную зону видимости; заменяется на этапе компиляции.

    (!) Следует отметить, что, как и у определения, так и у оператора const имеется ограничение на количество символов в названии – 31 символ.

    Макросы

    Макросы (в данном случая имеется в виду function-like macro, т.е. функция-подобный макрос) – важнейшая часть препроцессора, которая может обрабатывать полученные пользовательские данные и распоряжаться ими. В программировании макросы используются довольно часто, это обусловлено тем, что в программировании очень много одинаковых операций.

    Синтаксис

    Синтаксис макроса стоит из нескольких частей:
    Код:
    #define <название и его содержимое><конец макроса>  <значение для переопределения>
    Примечание:
    • От начала названия и до конца макроса не должно быть ни единого пробела, иначе будет ошибка. Однако, чтобы парсить пробелы необходимо использовать ascii-идентификаторы символов. Например, ascii-код для пробела – '\32;'
    • Первый символа макроса должен состоять из букв латинского алфавита или знаков ‘_’, ‘@’. Последующие же символы могут использовать и цифры.
    • В третьей же части использовать пробелы можно.


    Параметры

    Параметры являются неотъемлемой частью макрофункций, ведь с помощью них передаётся вся пользовательская информация.
    Параметры в макрофункциях задаются с помощью процента и номера аргумента.
    Код:
    #define macrofunc(%0,%1) %0 %1
    Опасные моменты использования параметров

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

    Перейдём к рассмотрению примера:
    PHP код:
    #define macrofunc(%0) (8 * %0)

    main()
    {
        
    printf("%d"macrofunc(5));

    В выводе ожидаем 80, а получаем 45. Дело в том, что макрос просто подставляет код туда, куда указанно. Он не определяет последовательность операций и т.п.
    Для того чтобы избежать данную проблему необходимо использовать круглые скобки, которые говорят о том, что начальной операцией является выражение в скобках.
    PHP код:
    #define macrofunc(%0) (8 * (%0))

    main()
    {
        
    printf("%d"macrofunc(5));

    Теперь все правильно. Итак, давайте выведем несколько правил, которые помогут избежать выше указанную проблему:
    • Скобки вокруг всего выражения;
    • Скобки вокруг каждого параметра;

    Однако, все выше перечисленные правила не помогут в случае, если вы используете инкрементацию/декрементацию в параметре.

    Рассмотрим пример:
    PHP код:
    #define macrofunc(%0) ((%0) * (%0))

    main()
    {
        new 
    x;
        
    printf("%d"macrofunc(++x));

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

    Переход на новую строку

    Для читаемости макрофункций используется обратный слеш, которые позволяет определить переход к новой строчке. Кроме того, это работает практически для каждой препроцессорной директивы.

    Перейдём к примеру:
    PHP код:
    #define SOME_MACRO(%0) \
        
    forward SOME_%0(); \
        public 
    SOME_%0(); 
    Также мы можем сделать и при обращении к макрофункциям:
    PHP код:
    #define SOME_MACRO_FUNC(%0,%1) \
        
    (%+ %1)

    main()
    {
        
    SOME_MACRO_FUNC(0, \
            
    \
        );


    Другие препроцессорные директивы

    #include и #tryinclude

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

    Главным отличием #include и #tryinclude является то, что последний не выводит ошибок, если файл не был загружен.

    #assert

    Проверяет указанное выражение. Если выражение возвращает нуль, то выдаёт ошибку.

    #if, #endif, #elseif, #else

    Начнём с того, что у каждой директивы #if должна быть соответствующая директива #endif. Кроме того, между данными препроцессорными директивами может располагаться любое количество директив #elseif. Однако, допускается не более одной директивы #else.
    PHP код:
    #define SOME_CONSTANT (0xFFFFFFFF)

    #if SOME_CONSTANT == 0
        #define SOME_CONSTANT_1 0
    #elseif SOME_CONSTANT > 0
        #define SOME_CONSTANT_1 1
    #elseif SOME_CONSTANT < 0
        #define SOME_CONSTANT_1 2
    #else
        #error Opss
    #endif 

    #endinput

    Данная препроцессорная директива указывает на то, что компилятор не должен читать последующий код, т.е. игнорировать его.
    PHP код:
    #if defined _PRO_PAWN_RU
        #endinput
    #endif

    #define _PRO_PAWN_RU 

    #error

    Директива выдаёт ошибку с указанным текстом при компиляции.
    PHP код:
    #error Some text 

    #undef

    Удаляет макрофункцию или константу. Синтаксис данной директивы следующий:
    Код:
    #undef <имя>

    Строки

    В препроцессоре существует оператор “#” помещающий значение в двойные кавычки. Например, рассмотрим код:
    PHP код:
    #define TO_STR(%0) (#%0)

    main()
    {
        
    printf("%s"TO_STR(pro-pawn.ru));

    Данный код выведет "pro-pawn.ru" в консоль.

    Вывод

    Несмотря на то, что препроцессор является хорошим инструментом, его стоит опасаться. Существует немалое количество ошибок, которые могут изменить логику вашего скрипта. Используйте препроцессор аккуратно.


    Если у вас появились какие-то вопросы, или вы думаете, что я что-то забыл, напишите об этом.


    Автор: VVWVV
    Исключительно для pro-pawn.ru

    Копирование данной статьи на других ресурсах без разрешения автора запрещено!
    Последний раз редактировалось VVWVV; 10.01.2017 в 08:04.

  2. 3 пользователя(ей) сказали cпасибо:
    Daniel_Cortez (16.06.2018) DCPSHER (16.06.2018) Enot (11.10.2017)
  3. #2
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±
    Интересует вот такой момент:
    Можно ли как-то посмотреть результаты работы Препроцессора?
    Т.е. промежуточное состояние между окончанием его работы и началом компиляции. Чтобы хоть как-то иметь возможность отдебажить макросы.
    Не представляю, как без нечто подобного Y_Less или Slice делали кучи макросов.

  4. #3
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от DCPSHER Посмотреть сообщение
    Интересует вот такой момент:
    Можно ли как-то посмотреть результаты работы Препроцессора?
    Т.е. промежуточное состояние между окончанием его работы и началом компиляции. Чтобы хоть как-то иметь возможность отдебажить макросы.
    Не представляю, как без нечто подобного Y_Less или Slice делали кучи макросов.
    Используйте флаг -l при компиляции, чтобы создать файл с результатом работы препроцессора.

  5. 2 пользователя(ей) сказали cпасибо:
    DCPSHER (17.06.2018) pawnoholic (16.06.2018)
  6. #4
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±
    Цитата Сообщение от VVWVV Посмотреть сообщение
    Используйте флаг -l при компиляции, чтобы создать файл с результатом работы препроцессора.
    Огромное спасибо. Очень помогло мне! Никак не мог найти в гугле.

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •