宏与静态内联?

时间:2014-12-14 13:57:35

标签: c c-preprocessor

使用宏而不是静态内联方法有什么显着的好处吗?特别是,如何使用静态内联方法在调用链中进一步传递varargs,这可以使用宏一步完成?

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

这只是一个简单的例子,但我仍然很好奇是否有使用静态内联的相同方法,而不使用va_args步骤。

编译器是否一直在内联静态内联方法?他们的体型怎么样?如何调用任意子方法?如果我使用多个宏,则所有宏都会编译成单个表达式,因此编译器可能更容易进行优化。编译器是否足够智能将多级静态内联调用转换为单个表达式?

1 个答案:

答案 0 :(得分:3)

使用宏而不是静态内联方法有什么显着的好处吗?

宏不进行类型检查,也不评估它们的参数,这会带来巨大的威力和巨大的危险。

所以(引用一个众所周知的例子)

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

似乎比

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

因为它不需要int参数(即适用于支持>运算符的所有类型),除了

这一事实
  • 评估ab两次(考虑MAX(a++,b++)
  • 它有可能出现运营商优先问题

这解决了第二个问题:

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

如何使用静态内联方法在调用链中进一步传递varargs,这可以使用宏一步完成?

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

[编译器] [始终]内联static inline方法吗?

不,编译器可以自由地做它想做的事情。它可以内联它们,或者为每个编译单元生成一组目标代码。但是,至少在理论上,它可以对#define&#d; d宏执行相同的操作。编译器不会总是将多个级别的内联宏转换为单个表达式,因为即使单个内联宏实际上也不能内联编码;通常,编译器在确定这是否是个好主意时比程序员更聪明。