2014-12-14 3 views
1

Есть ли существенные преимущества при использовании макросов вместо статических встроенных методов? В частности, как можно реализовать передачу varargs дальше по цепочке вызовов с помощью статического встроенного метода, который можно сделать за один шаг с помощью макроса?Макросы против статического встроенного?

#define myprintf(fmt, args...) printf (fmt, args) 

Это всего лишь простой пример, но я все еще интересно, если есть эквивалент способ сделать это, используя статический встроенный без использования va_args шага.

Также всегда, чтобы компилятор применял статические встроенные методы? Как насчет их размера? Как насчет вызова произвольных подтекстов? Если я использую несколько макросов, все они компилируются в одно выражение, поэтому оптимизатор, вероятно, проще оптимизировать. Является ли компилятор достаточно умным, чтобы преобразовать несколько уровней статических встроенных вызовов в одно выражение?

+0

«Является ли компилятор всегда достаточно умным ...?» Это зависит от компилятора. – Barmar

+0

C99 имеет переменные аргументы макросов. –

+0

Я исправил пробел в вашем примере кода. Как было написано, 'myprintf' не был макрофункцией и был заменен на' (fmt, args ...) printf (fmt, args) ', где он появляется. – mafso

ответ

2

Есть ли существенные преимущества при использовании макросов вместо статических встроенных методов?

Макросы не выполняют проверку типов и не оценивают их аргументы, которые приносят большую силу и большую опасность.

Так (цитата хорошо известный пример)

#define MAX(a,b) (a>b):a?b 

может показаться, что лучшей идеей, чем

static inline int max(a,b) { return (a>b):a?b; } 

, поскольку он не требует int аргумента (т.е. будет работать для всех типов которые поддерживают оператора >), за исключением того факта, что

  • Он оценивает a и b дважды (рассмотреть MAX(a++,b++))
  • Она имеет потенциал для оператора старшинства вопросы

Это решает второй:

#define MAX((a),(b)) (((a)>(b)):(a)?(b))`) 

Как можно осуществить прохождение списков параметров далее вниз по цепочке вызовов со статическим встроенным методом, который можно сделать за один шаг с помощью макроса?

C99 поддерживает переменные макросы, а gcc имеет (нестандартные) расширения до here.

На самом деле есть два формата:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__) 

где __VA_ARGS__ получает заменить переменным числом элементов; это стандарт C99.

gcc также обеспечивает:

#define debug(format, args...) fprintf (stderr, format, args) 

, где args может представлять более одного аргумента.

В первой формулировке, с gcc только, вы можете справиться с аргументами опущены полностью и избежать лишней запятой с помощью оклейки оператора макросъемки ##, т.е .:

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__) 

Там есть no standards-based way достижения этого.

[Есть ли] компилятор [всегда] inline static inline методов?

Нет, компилятор может делать все, что захочет. Он может встроить их или создать один набор объектных кодов на единицу компиляции. Однако, по крайней мере теоретически, он мог бы сделать то же самое с макросами #define 'd. Компилятор не всегда будет преобразовывать несколько уровней встроенных макросов в одно выражение, так как даже один встроенный макрос не может быть фактически закодирован inline; обычно компилятор умнее программиста при определении того, является ли это хорошей идеей или нет.

+0

'#define debug (...) fprintf (stderr, __VA_ARGS __)' может достичь такого же эффекта здесь, не прибегая к расширениям gcc. –

+0

@PaulGriffiths ваша точка в том, что '...' вещь без аргумента является нестандартной, '## __VA_ARGS__' является нестандартной, но только' __VA_ARGS__' является стандартной (в отличие от них все являются gcc-расширением) ? Я что это правильно, и я исправлю. – abligh

+0

Да, именно, '__VA_ARGS__' является стандартным с C99, но для этого требуется предоставить хотя бы один аргумент, поэтому в моем примере показано, как получить такой же эффект, как' ## __VA_ARGS__', на основе стандартов. –

Смежные вопросы