Продолжаем повествование о прагма-выражениях, которые были описаны в обзорной статье.
Напомню что условные прагмы влияют на генерацию кода во время прекомпиляции и компиляции, но не во время исполнения программы.
С помощью условных прагм вы влияете, учитывается ли код реализации при компиляции. Например, вы можете сделать это зависимым от того, объявлена ли определенная переменная, существует ли определенный функциональный блок и т.д.
Прагма {define}
Имеет синтаксис:
{define <identifier> <string>}
Задает какой либо идентификатор, который в последствии будет использоваться. Стоит помнить про область видимости. Данный идентификатор будет виден только в пределах того места где он был определен прагмой {define}.
Определение возможно только в разделе кода.
Чтобы было понятнее приложу скриншоты объявления и результаты выполнения.
Если вы заметили, то там еще есть флаги для идентификаторов С и D, С объявлен в глобальных данных, а D в POU программа, где мы и вызываем этот FB.
Прагма {undefine}
Оператор {define} идентификатора <identifier> отменяется, и с этого момента идентификатор снова становится неопределенным. Прагма игнорируется, если указанный идентификатор вообще не определен.
Рассмотрим несколько идентификаторов.
В результате выполнения все хорошо скомпилировалось и все биты были взведены.
Теперь мы немного усложним данные директивы.
Логика здесь в следующем. Если нет C, то определяем идентификатор D.
Прагмы для условной компиляции
Назначение условных прагм - повлиять на генерацию кода в процессе пре-компиляции или в процессе компиляции. Язык реализации ST поддерживает эти прагмы.
Это как раз те условия, что мы писали выше. Единственное, что в блоке {IF} есть специальные операторы, которые позволяют нам гибко контролировать условия компиляции.
Оператор defined(<identifier>)
Этот оператор приводит к тому, что выражению присваивается значение ИСТИНА. Требование состоит в том, чтобы идентификатор <identifier> был определен с помощью инструкции {define} и не определялся снова после этого с помощью инструкции {undefine}; в противном случае возвращается ЛОЖЬ.
Примером этому служит все что было выше.
Оператор defined (variable: variable)
Этот оператор приводит к тому, что выражению присваивается значение ИСТИНА, если переменная объявлена в текущей области; в противном случае возвращается ЛОЖЬ.
Если мы возьмем и напишем следующий код:
И попытаемся скомпилировать данную программу, то получим сообщение:
Следует только объявить данную переменную, как все скомпилируется без сообщения и переменной rSum будет присвоено значение 5.
Оператор defined (type: identifire)
Возвращает TRUE когда у нас есть объявленная переменная с соответствующим пользовательским типом данных.
Например: Нам требуется понять есть ли в данном функциональном блоке переменная с каким-то определенным пользовательским типом.
В исходном коде у нас есть и данный тип и прагма условие и какие-то действия.
Никогда не присваивайте значения каким-то объявленным переменным во время прагма выражений для условной компиляции если вы не полностью осознаете последствия.
При выполнении кода у нас будет присвоено значение равное 45.
В то же время стоит помнить
Прагма выражения чувствительны к регистру
И если type вдруг изменится на TYPE то мы получим ошибку
А теперь почему не стоит инициализировать значения переменных при проверки типов. Допустим если мы все оставим как у меня, то может получится следующая ошибка.
Компилятор нам разумеется сообщит об ошибке, но не всегда, особенно если пользовательские типы совпадут.
Оператор defined (pou: <pou name> )
Условный оператор возвращает TRUE если есть FB или Action с таким именем.
Вопрос. Какое значение будет у переменной xInit в следующем примере:
Когда я только начал разбираться, то был уверен, что xInit будет FALSE, однако:
Весь фокус заключался в том, что у меня в проекте есть POU TCPLogic. Так что данное условие удобно применять при проверки целостности. а все ли мы подтянули из нужных нам библиотек.
Оператор defined (task: <identifire)
Возвращает True если мы имеем task с нужным именем.
Рассмотрим список моих задач
В нем есть ровно две задачи. Одна основная другая на визуализацию. В FB я создам условие, при котором, если будет отсутствовать в проекте необходимый TASK, переменная xError станет True.
Так как TASK с идентификатором MainTask1 у меня нет, то мы получили ошибку.
Оператор defined (IsSimulationMode)
Возвращает True, Когда мы находимся в режиме симуляции(эмуляции).
Ну тут даже не нужен пример.
Оператор defined (IsLittleEndian)
Наверно самая нужная прагма, которая позволяет нам правильно представлять данные.
Итог
В данной статье я описал половину доступных прагма операторов для условных выражений. В следующий раз у нас будет остаток и еще чуть чуть про пользовательские прагма-выражения, т.к. они очень нужны. Это всего лишь теоретический материал. Найдете ли вы ему практическое применение неизвестно, но я убежден, что каждый должен отлично знать инструмент на котором работает.
Вопросы и предложения можно направлять по адресу info@engcore.ru