Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Использование аргументов с #define

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

Пример:

#define abs(A) (((A) > 0)?(A): -(A))

Каждое вхождение выражения abs(arg) в тексте программы заменяется на

((arg) > 0)? (arg): -(arg),

причем параметр макроопределения А заменяется на arg.

Пример:

/* макроопределение с аргументами */ #define SQUARE(x) x*x#define PR(x) printf("x равно %d.\n", x)main(){ int x = 4; int z; z = SQUARE(x); PR(z); //16 z = SQUARE(2); PR(z); //4 PR(SQUARE(x)); //PR(16) =16 PR(SQUARE(x+2)); // PR(x+2*x+2)=14 PR(100/SQUARE(2)); // PR(100/2*2)=100 PR(SQUARE(++x)); //PR(++x*++x)=36}

Всюду, где в нашей программе появляется макроопределение SQUARE(x), оно заменяется на x*x. В отличие от наших прежних примеров, при использовании этого макроопределения мы можем совершенно свободно применять символы, отличные от x. В макроопределении ' x ' замещается символом, использованным в макровызове программы. Поэтому макроопределение SQUARE(2) замещается на 2*2. Таким образом, x действует как аргумент. Однако, аргумент макроопределения не работает - точно так же, как аргумент функции. Вот результаты выполнения программы:

z равно 16.z равно 4.SQUARE(x) равно 16.SQUARE(x+2) равно 14. 100/SQUARE(2) равно 100.SQUARE(++x) равно 36.

Первые две строки очевидны. Заметим, что даже внутри двойных кавычек в определении PR переменная замещается соответствующим аргументом. Все аргументы в этом определении замещаются. Рассмотрим третью строку:

PR(SQUARE(x));

Она становится следующей строкой:

printf("SQUARE(x) равно %d.\n", SQUARE(x));

после первого этапа макрорасширения. Второе SQUARE(x) расширяется, превращаясь в x*x, а первое остается без изменения, потому что теперь оно находится внутри кавычек в операторе программы, и таким образом защищено от дальнейшего расширения. Окончательно строка программы содержит

printf("SQUARE(x) равно %d.\n",x*x);

и выводит на печать

SQUARE(x) равно x*x.

Аргумент в кавычках препроцессорм не заменяется! Если макроопределение включает аргумент с двойными кавычками, то аргумент будет замещаться строкой из макровызова. Но после этого он в дальнейшем не расширяется, даже если строка является еще одним макроопределением. В нашем примере переменная x стала макроопределением SQUARE(x) и осталась им. Вспомним, что x=4. Это позволяет предположить, что SQUARE(x+2) будет равно 6*6 или 36. Но напечатанный результат говорит, что получается число 14. Причина такого результата такова: препроцессор не делает вычислений. Он только замещает строку. Всюду, где наше определение указывает на x, препроцессор подставит строку x+2.

Таким образом,

x*x становится x+2*x+2

Если x равно 4, то получается

4+2*4+2=4+8+2=14

 

Многие задачи можно решать, используя макроопределение с аргументами или функцию. Что из них следует применять? На этот счет нет строгих правил, но есть некоторые соображения.

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

Выбор макроопределения приводит к увеличению объема памяти, а выбор функции - к увеличению времени работы программы. Макроопределение создает строчный код, т.е. мы получаем оператор в программе. Если макроопределение применить 20 раз, то в программу вставится 20 строк кода. Если мы используем функцию 20 раз, то у нас будет только одна копия операторов функции. Однако управление программой следует передать туда, где находится функция, а затем вернуться в вызывающую программу, а на это потребуется больше времени, чем при работе со строчными кодами. Так что думайте, что выбирать!

Преимущество макроопределений заключается в том, что при их использовании нам не нужно беспокоиться о типах переменных, т.к. макроопределения имеют дело с символьными строками, а не с фактическими значениями. Tак наше макроопределение SQUARE(x) можно использовать одинаково хорошо с переменными типа int или float.

Итак:

Отличие от функций:

1. Вызов функции передает значение аргумента в функцию во время выполнения программы. Макровызов передает строку аргументов в программу до ее компиляции.

2. Так как выражение для вычисления макроопределения подставляется непосредственно в программу, то размер ее увеличивается. Но при этом не затрачивается время на вызов функции, которая может быть использована вместо макроопределения. То есть использование макроопределений повышает быстродействие программы.

Оператор #

Если разместить оператор # перед параметром в макроопределении, препроцессор создаст строковую константу из параметра при вызове макроопределния. Например, задав макроопределение как

#define str(x) #x

И сделав вызов макроопределения следующим образом:

str(testing)

получим строку “testing”, которую создал препроцессор. Поэтому следующий вызов функции printf

printf(str(Programming in C\n));

будет эквивалентен вызову

printf(“Programming in C\n”);

Препроцессор просто расставляет двойные кавычки вокруг аргумента. Двойные кавычки или обратная черта в аргументах препроцессором сохраняются, поэтому вызов:

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 до х100. Можно создать макроопределение, в которое в качестве параметра будут передаваться целые значения от 1 до 100 и затем отображаться вместе с именем х:

х1,х2,..х100

#define printx(n) printf(“%d\n”,x##n)

При этом вызов

printx(20)

даст результат “x20”

<== предыдущая лекция | следующая лекция ==>
Общие сведения. В интегрированную среду подготовки программ на Си или в компилятор языка как обязательный компонент входит препроцессор | Включение файла: #include
Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 614; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.02 сек.