Я использую синтаксический анализатор из поваренной книги C# 3.0.
Все примеры из этой книги могут быть загружены здесь: http://examples.oreilly.com/9780596516109/
Поиск 'Аргументов' и Вы найдете его. Необходимо сделать некоторые небольшие изменения кода для вытаскивания его из всего этого в собственный класс, но это не большая проблема.
Это поддерживает все Ваши точки кроме последних двух (параметр, объединяющийся & пропавшие без вести пространства).
В макросах есть пара строго злобных вещей.
Они обрабатывают текст и не имеют области видимости. Если вы #define foo 1
, то любое последующее использование foo
в качестве идентификатора не удастся. Это может привести к странным ошибкам компиляции и труднодоступным ошибкам времени выполнения.
Они не принимают аргументы в обычном смысле. Вы можете написать функцию, которая будет принимать два значения int
и возвращать максимальное значение, поскольку аргументы будут вычисляться один раз, а значения будут использоваться после этого. Вы не можете написать макрос для этого, потому что он будет оценивать по крайней мере один аргумент дважды и терпеть неудачу с чем-то вроде max (x ++, --y)
.
Также есть распространенные ошибки. В них сложно получить сразу несколько утверждений,
В большинстве других ответов обсуждается, почему макросы злы, включая то, как в вашем примере есть общий макрос использовать недостаток. Вот пример Страуструпа: http://www.research.att.com/~bs/bs_faq2.html#macro
Но ваш вопрос заключался в том, для чего макросы все еще подходят. Есть некоторые вещи, в которых макросы лучше, чем встроенные функции, и именно здесь вы делаете то, что просто может ' Это может быть сделано с помощью встроенных функций, таких как:
assert ()
) offsetof ()
используют имя типа для создания операции приведения) Но с языком, который имеет встроенные функции, более распространенное использование макросов не должно быть необходимости. Я даже не хочу использовать макросы, когда имею дело с компилятором C, который не поддерживает встроенные функции.
Для этого конкретного макроса, если я использую его следующим образом:
int x=1;
x = radian2degree(x);
float y=1;
y = radian2degree(y);
проверки типов не будет, и x, y будут содержать другие значения.
Кроме того, следующий код
float x=1, y=2;
float z = radian2degree(x+y);
не будет делать то, что вы думаете, поскольку он будет преобразован в
float z = x+y*0.017453292519;
вместо
float z = (x+y)+0.017453292519;
, что является ожидаемым результатом.
Это всего лишь несколько примеров неправильного поведения и неправильного использования макросов.
Править
вы можете увидеть дополнительные обсуждения этого здесь
Препроцессор компилятора - штука непростая, а значит, ужасный кандидат для хитрых уловок. Как отмечали другие, компилятору легко неправильно понять ваше намерение с макросом, а вам легко неправильно понять, что на самом деле макрос будет делать, но, что наиболее важно, вы не можете войти в макросы в отладчике!
по возможности всегда используйте встроенную функцию. Они безопасны для типов и не могут быть легко переопределены.
определения могут быть переопределены до неопределенных, и здесь нет проверки типов.
Макросы - зло, потому что вы можете в конечном итоге передать ему больше, чем переменную или скаляр, и это может разрешить нежелательное поведение (определите макрос max для определения max между a и b, но передайте макросу a ++ и b ++ и посмотрим, что произойдет).
Если ваша функция все равно будет встроена, разницы в производительности между функцией и макросом нет. Однако есть несколько различий в удобстве использования между функцией и макросом, и все они в пользу использования функции.
Если вы правильно построите макрос, проблем не будет. Но если вы используете функцию, компилятор каждый раз будет делать это правильно за вас. Таким образом, использование функции затрудняет написание плохого кода.
Макросами относительно часто злоупотребляют, и можно легко сделать ошибки, используя их, как показано в вашем примере. Возьмите выражение radian2degree (1 + 1):
В общем, макросы злы, потому что они выглядят как функции , поэтому они обманом заставляют вас использовать их так же, как функции , но у них есть собственные тонкие правила . В этом случае правильнее было бы написать это так (обратите внимание на скобки вокруг a):
#define radian2degree(a) ((a) * 57.295779513082)
Но вы должны придерживаться встроенных функций. См. Эти ссылки в C ++ FAQ Lite для получения дополнительных примеров вредоносных макросов и их тонкостей: