Препроцессор Objective-C не является частью компилятора, но является отдельным этапом в процессе компиляции. Проще говоря, препроцессор Objective-C — это всего лишь инструмент подстановки текста, который инструктирует компилятор выполнить необходимую предварительную обработку перед фактической компиляцией. Мы будем называть препроцессор Objective-C OCPP.
Все команды препроцессора начинаются с символа решетки (#). Это должен быть первый непустой символ, и для удобства чтения директива препроцессора должна начинаться с первого столбца. В следующем разделе перечислены все важные директивы препроцессора —
Sr.No. | Директива и описание |
---|---|
1 |
#define Заменяет макрос препроцессора |
2 |
#включают Вставляет определенный заголовок из другого файла |
3 |
#undef Определяет макрос препроцессора |
4 |
#ifdef Возвращает true, если этот макрос определен |
5 |
#ifndef Возвращает true, если этот макрос не определен |
6 |
#если Проверяет, верно ли условие времени компиляции |
7 |
#else Альтернатива для #if |
8 |
#elif # еще #if в одном утверждении |
9 |
#endif Завершает препроцессор условно |
10 |
#ошибка Распечатывает сообщение об ошибке на stderr |
11 |
#pragma Выдает специальные команды компилятору с использованием стандартизированного метода |
#define
Заменяет макрос препроцессора
#включают
Вставляет определенный заголовок из другого файла
#undef
Определяет макрос препроцессора
#ifdef
Возвращает true, если этот макрос определен
#ifndef
Возвращает true, если этот макрос не определен
#если
Проверяет, верно ли условие времени компиляции
#else
Альтернатива для #if
#elif
# еще #if в одном утверждении
#endif
Завершает препроцессор условно
#ошибка
Распечатывает сообщение об ошибке на stderr
#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. Это полезно, если вы передаете флаг -DDEBUG компилятору gcc во время компиляции. Это определит DEBUG, так что вы можете включать и выключать отладку на лету во время компиляции.
Предопределенные макросы
ANSI C определяет количество макросов. Хотя каждый из них доступен для использования в программировании, предопределенные макросы не должны изменяться напрямую.
Sr.No. | Макрос и описание |
---|---|
1 |
__ДАТА__ Текущая дата в виде символьного литерала в формате «МММ ДД ГГГГ» |
2 |
__ВРЕМЯ__ Текущее время как символьный литерал в формате «ЧЧ: ММ: СС» |
3 |
__ФАЙЛ__ Это содержит текущее имя файла в виде строкового литерала. |
4 |
__ЛИНИЯ__ Он содержит номер текущей строки в виде десятичной константы. |
5 |
__STDC__ Определяется как 1, когда компилятор соответствует стандарту ANSI. |
__ДАТА__
Текущая дата в виде символьного литерала в формате «МММ ДД ГГГГ»
__ВРЕМЯ__
Текущее время как символьный литерал в формате «ЧЧ: ММ: СС»
__ФАЙЛ__
Это содержит текущее имя файла в виде строкового литерала.
__ЛИНИЯ__
Он содержит номер текущей строки в виде десятичной константы.
__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")
Stringize (#)
Оператор stringize или number-sign (‘#’), когда используется в определении макроса, преобразует параметр макроса в строковую константу. Этот оператор может использоваться только в макросе, который имеет указанный аргумент или список параметров. Например —
#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 в token34, и здесь мы использовали как stringize, так и вставку токена .
Определенный () оператор
Определяемый препроцессором оператор используется в константных выражениях, чтобы определить, определен ли идентификатор с помощью #define. Если указанный идентификатор определен, значение равно true (не ноль). Если символ не определен, значение равно 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; }
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —