c - 宏与静态内联?

标签 c c-preprocessor

使用宏代替静态内联方法有什么显着的好处吗?特别是,如何使用静态内联方法在调用链中进一步向下传递可变参数,而静态内联方法可以使用宏在一个步骤中完成?

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

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

编译器内联静态内联方法是否总是如此?它们的大小呢?调用任意子方法怎么样?如果我使用多个宏,所有宏都会编译成一个表达式,因此编译器可能更容易优化。编译器是否总是足够聪明,可以将多级静态内联调用转换为单个表达式?

最佳答案

使用宏代替静态内联方法有什么显着的好处吗?

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

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

#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))
    

    如何使用可以使用宏一步完成的静态内联方法在调用链中进一步传递可变参数?

    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只是,您可以处理完全省略的参数,并使用粘贴宏运算符 ## 避免多余的逗号。 , IE。:
    #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
    

    no standards-based way实现这一目标。

    [是否] 编译器 [总是] 内联 static inline方法?

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

    关于c - 宏与静态内联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27470039/

    相关文章:

    c - 整数计算未按预期工作

    c - Tiva 上的 I2C 接口(interface)

    c - "#if ..."(带有省略号)是做什么的?

    C 预处理器令人困惑的行为

    我们可以删除 C 宏定义中参数周围的括号吗?

    c - 不工作/使用自己的 Strncpy 函数

    检查 pthread 可取消状态

    c - 为什么指针内部的值不允许为 "%s"?

    c - 将#define 与函数一起使用

    c - 在 VS 调试器 : any way to hover and see values? 中使用#define