Чтение онлайн

на главную

Жанры

Программирование на Objective-C 2.0
Шрифт:

Последний оператор if намного понятнее, чем предыдущий. Конечно, данное определение позволяет проверить на високосный год только переменную year, но мы можем написать определение, с помощью которого можно проверить на високосный год любое выражение. Для этого нужно включить в определение один или несколько аргументов.

IS_LEAP_YEAR можно определить с аргументом у следующим образом. #define IS_LEAP_YEAR(y) у % 4 == 0 && у % 100 != 0 \ || у % 400 == 0

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

Используя это определение, напишем оператор if ( IS_LEAP_YEAR (year))

Оператор проверяет, является ли значение для year високосным годом. Можно написать аналогичное выражение для nextYear. if ( IS_LEAP YEAR (nextYear))

В этом операторе определение для IS_LEAP_YEAR непосредственно подставляется в оператор if с заменой аргумента у на nextYear. В результате компилятор будет обрабатывать следующий оператор. if ( nextYear % 4 == 0 && nextYear % 100 != О |j nextYear % 400 == 0)

Определения часто с одним или несколькими аргументами то называют макросами. В следующем макросе представлен квадрат его аргумента. #define SQUARE(x) х * х

В определении для SQUARE необходимо учитывать возможность следующей ошибки. Исходя из нашего описания, оператор у = SQUARE (v);

присваивает у значение V2. Но в операторе у = SQUARE (v+1);

переменной не присваивается значение (v + 1)2, как ожидалось. Поскольку в определении этого макроса препроцессор выполняет подстановку текста вместо аргумента, здесь получится следующее выражение: у = v + 1 * v + 1;

Чтобы решить проблему, нужно использовать в определении макроса SQUARE круглые скобки. #define SQUARE(x) ( (х) * (х))

Определение может показаться несколько странным, но помните, что х будет заменяться подставляемым выражением. Теперь оператор у = SQUARE (v+ 1);

будет правильно обработан как У = ((v+ 1) * (v+ 1)); Следующий макрос позволяет создавать новые дроби из нашего класса Fraction. #define MakeFract(x.y) ([[Fraction alloc] initWith: x over: y]])

Теперь для сложения дробей nl/dl и n2/d2 можно писать такие выражения, как myFract = MakeFract (1, 3); // Создание дроби 1/3

или sum = [MakeFract (nl, d1) add: MakeFract (n2, d2)];

Макросы удобны для работы с условными выражениями. В следующей строке определяется макрос с именем МАХ, определяющий максимальное из двух значений. #define MAX(a,b) { ((а) > (Ь)) ? (а): (Ь))

С помощью этого макроса можно писать такие операторы, как limit = МАХ (х + у, minValue);

Переменной limit присваивается максимальное из двух значений: х + у и minValue. Все определение МАХ заключено в круглые скобки, чтобы правильно обрабатывать такие выражения, как МАХ (х, у)* 100

Каждый аргумент тоже заключен в круглые скобки, чтобы правильно обрабатывать такие выражения, как МАХ (х & у, z)

Оператор & — это побитовый оператор AND, и он имеет меньший приоритет, чем оператор > в данном макросе. Без этих круглых скобок оператор > обрабатывался бы раньше побитового AND, что давало бы неверный результат.

В следующем макросе проверяется, является ли символ строчной буквой. #define IS_LOWER_CASE(x) ( ((х) >= 'а') && <(х) <= ’z') )

С помощью этого макроса можно писать такие выражения, как if ( IS_LOWER_CASE (с))

Этот макрос можно даже использовать в определении другого макроса, чтобы преобразовывать символ из нижнего регистра в верхний (делать строчную букву прописной), не изменяя другие символы. #define T0_UPPER(x) ( IS_LOWER_CASE (х) ? (х) -'a' + 'A' : (х))

Здесь мы снова работаем со стандартным набором символов ASCII. В части II, когда будут описываться объекты-строки, вы увидите, как выполнять преобразование символов из одного регистра в другой для международных наборов символов (Unicode). Оператор

Если поместить символ # перед параметром в определении макроса, препроцессор создаст строку-константу в стиле С из аргумента макроса при его вызове. Например, определение #define str(x) # х

при последующем вызове str (testing)

будет раскрыто препроцессором как "testing"

Например, вызов printf printf (str ("Программировать на Objective-C интересно""));

эквивалентен printf ("Программировать на Objective-C интересно");

Препроцессор заключает в кавычки фактический аргумент макроса. Препроцессор сохраняет в аргументе все кавычки и обратные слэши. Поэтому вызов str ("hello")

даст в результате "\"hello\"" Более близкий к практике пример оператора # представляет следующее определение макроса. define printint(var) printf (# var " = %i\n", var) Этот макрос используется для вывода значен ия целой переменной. Если count — переменная целого типа со значением 100, то оператор

printint (count); будет раскрыт как

printf ("count" " = %i\n", count); Компилятор выполнит конкатенацию двух смежных литеральных строк, чтобы создать одну строку. Поэтому после конкатенации оператор примет следующий вид.

printf ("count = %i\n", count); ### Оператор ## В определении макроса оператор ## сливает два маркера. Он ставится перед именем параметра макроса (или после него). Препроцессор берет фактический аргумент, указанный при вызове макроса, и создает один маркер из этого аргумента и из маркера, который следует за ## или предшествует ##. Предположим, что у нас имеется список переменных от х1 до хЮО. Мы можем написать макрос с вызовом printx, который принимает в качестве аргумента значение от 1 до 100 и выводит значение соответствующей переменной. define printx(n) printf ("%i\n", x ## n) Часть x ## n указывает, что нужно взять маркеры, стоящие перед и после ## (соответственно букву х и аргумент п), и создать из них один маркер. Поэтому вызов

Поделиться:
Популярные книги

Последний Паладин. Том 13

Саваровский Роман
13. Путь Паладина
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 13

Телохранитель Цесаревны

Зот Бакалавр
5. Герой Империи
Фантастика:
фэнтези
боевая фантастика
5.25
рейтинг книги
Телохранитель Цесаревны

Бастард Императора. Том 5

Орлов Андрей Юрьевич
5. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 5

Меченный смертью. Том 2

Юрич Валерий
2. Меченный смертью
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Меченный смертью. Том 2

Кодекс Охотника. Книга ХХ

Винокуров Юрий
20. Кодекс Охотника
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга ХХ

Путь Шедара

Кораблев Родион
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Путь Шедара

Я снова граф. Книга XI

Дрейк Сириус
11. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я снова граф. Книга XI

На границе империй. Том 10. Часть 10

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 10

Шайтан Иван 6

Тен Эдуард
6. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
7.00
рейтинг книги
Шайтан Иван 6

Клан

Русич Антон
2. Долгий путь домой
Фантастика:
боевая фантастика
космическая фантастика
5.60
рейтинг книги
Клан

Железный Воин Империи VII

Зот Бакалавр
7. Железный Воин Империи
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Железный Воин Империи VII

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Наследие Маозари 5

Панежин Евгений
5. Наследие Маозари
Фантастика:
фэнтези
юмористическое фэнтези
5.00
рейтинг книги
Наследие Маозари 5

Первый среди равных. Книга IX

Бор Жорж
9. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IX