КАТЕГОРИИ: Архитектура-(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 действует как аргумент. Однако, аргумент макроопределения не работает - точно так же, как аргумент функции. Вот результаты выполнения программы: Первые две строки очевидны. Заметим, что даже внутри двойных кавычек в определении 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”
Дата добавления: 2014-01-07; Просмотров: 642; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |