Препроцессоры Objective-C

В Objective-C Preprocessorне является частью компилятора, но представляет собой отдельный шаг в процессе компиляции. Говоря упрощенно, препроцессор Objective-C - это просто инструмент для подстановки текста, который инструктирует компилятор выполнить необходимую предварительную обработку перед фактической компиляцией. Мы будем называть препроцессор Objective-C OCPP.

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

Sr. No. Директива и описание
1

#define

Заменяет макрос препроцессора

2

#include

Вставляет определенный заголовок из другого файла

3

#undef

Отменяет определение макроса препроцессора

4

#ifdef

Возвращает истину, если этот макрос определен

5

#ifndef

Возвращает истину, если этот макрос не определен

6

#if

Проверяет, истинно ли условие времени компиляции

7

#else

Альтернатива #if

8

#elif

#else an #if в одном заявлении

9

#endif

Завершает условный препроцессор

10

#error

Выводит сообщение об ошибке на stderr

11

#pragma

Выдает специальные команды компилятору, используя стандартизированный метод

Примеры препроцессоров

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

#define MAX_ARRAY_LENGTH 20

Эта директива указывает OCPP заменять экземпляры MAX_ARRAY_LENGTH на 20. Используйте #define для констант, чтобы улучшить читаемость.

#import <Foundation/Foundation.h>
#include "myheader.h"

Эти директивы предписывают OCPP получить файл foundation.h от Foundation Frameworkи добавьте текст в текущий исходный файл. Следующая строка указывает OCPP получитьmyheader.h из локального каталога и добавьте содержимое в текущий исходный файл.

#undef  FILE_SIZE
#define FILE_SIZE 42

Это указывает OCPP отменить определение существующего FILE_SIZE и определить его как 42.

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

Это указывает OCPP определять MESSAGE, только если MESSAGE еще не определен.

#ifdef DEBUG
   /* Your debugging statements here */
#endif

Это указывает OCPP выполнить обработку заключенных в него операторов, если определена DEBUG. Это полезно, если вы передаете компилятору gcc флаг -DDEBUG во время компиляции. Это определит DEBUG, так что вы можете включать и выключать отладку на лету во время компиляции.

Предопределенные макросы

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

Sr. No. Макрос и описание
1

__DATE__

Текущая дата в виде символьного литерала в формате «МММ ДД ГГГГ».

2

__TIME__

Текущее время в виде символьного литерала в формате "ЧЧ: ММ: СС".

3

__FILE__

Он содержит текущее имя файла в виде строкового литерала.

4

__LINE__

Он содержит текущий номер строки как десятичную константу.

5

__STDC__

Определяется как 1, если компилятор соответствует стандарту ANSI.

Давайте попробуем следующий пример -

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"File :%s\n", __FILE__ );
   NSLog(@"Date :%s\n", __DATE__ );
   NSLog(@"Time :%s\n", __TIME__ );
   NSLog(@"Line :%d\n", __LINE__ );
   NSLog(@"ANSI :%d\n", __STDC__ );
   
   return 0;
}

Когда приведенный выше код в файле main.m компилируется и выполняется, он дает следующий результат -

2013-09-14 04:46:14.859 demo[20683] File :main.m
2013-09-14 04:46:14.859 demo[20683] Date :Sep 14 2013
2013-09-14 04:46:14.859 demo[20683] Time :04:46:14
2013-09-14 04:46:14.859 demo[20683] Line :8
2013-09-14 04:46:14.859 demo[20683] ANSI :1

Операторы препроцессора

Препроцессор Objective-C предлагает следующие операторы, которые помогут вам в создании макросов:

Продолжение макроса (\)

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

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

Стринги (#)

Оператор преобразования строки или знака числа ('#') при использовании в определении макроса преобразует параметр макроса в строковую константу. Этот оператор может использоваться только в макросе с указанным аргументом или списком параметров. Например -

#import <Foundation/Foundation.h>

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

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

2013-09-14 05:46:14.859 demo[20683] Carole and Debra: We love you!

Вставка токена (##)

Оператор вставки токена (##) в определении макроса объединяет два аргумента. Он позволяет объединить два отдельных токена в определении макроса в один токен. Например -

#import <Foundation/Foundation.h>

#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
}

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

2013-09-14 05:48:14.859 demo[20683] token34 = 40

Как это произошло, потому что этот пример приводит к следующему фактическому выводу препроцессора:

NSLog (@"token34 = %d", token34);

В этом примере показано объединение токена ## n в токен34, и здесь мы использовали оба stringize и token-pasting.

Оператор defined ()

Препроцессор definedОператор используется в постоянных выражениях, чтобы определить, определен ли идентификатор с помощью #define. Если указанный идентификатор определен, значение истинно (ненулевое). Если символ не определен, значение false (ноль). Определяемый оператор определяется следующим образом -

#import <Foundation/Foundation.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   NSLog(@"Here is the message: %s\n", MESSAGE);  
   return 0;
}

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

2013-09-14 05:48:19.859 demo[20683] Here is the message: You wish!

Параметризованные макросы

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

int square(int x) {
   return x * x;
}

Мы можем переписать приведенный выше код с помощью макроса следующим образом:

#define square(x) ((x) * (x))

Макросы с аргументами должны быть определены с помощью #defineдирективу, прежде чем их можно будет использовать. Список аргументов заключен в круглые скобки и должен следовать сразу за именем макроса. Между именем макроса и открывающими скобками не допускается использование пробелов. Например -

#import <Foundation/Foundation.h>

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

int main(void) {
   NSLog(@"Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

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

2013-09-14 05:52:15.859 demo[20683] Max between 20 and 10 is 20