Препроцессоры 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