【问题标题】:Is this use of macros in C portable?在 C 语言中使用宏是可移植的吗?
【发布时间】:2020-11-07 18:42:09
【问题描述】:

此 C 语言程序定义了宏 START 和 END,它们生成运行时函数执行信息。动作 TRACE_START 和 TRACE_END 当然可以是任何东西,例如推送和弹出堆栈、动态分析等。此外,没有理由不能运行时可配置操作行为。这为某些类型的软件产品提供了许多有吸引力的可能性。

不利的一面是,将函数的左大括号和右大括号从 f(){} 重新定义为 f()START...END 可能会破坏许多自动工具。 接受这种情况, 这样做有什么影响?这种使用宏处理器是否可移植?

下面的代码使用 gcc --pedantic 正确编译。

#include <stdio.h>

#define START           {TRACE_START
#define END             TRACE_END}
#define TRACE_START     printf("ENTERING %s\n", __func__);
#define TRACE_END       printf("LEAVING %s\n", __func__);

int func()
START
    printf ("Hello World %s\n");
END

int main()
START
    func();
END

并产生输出

ENTERING main
ENTERING func
Hello World
LEAVING func
LEAVING main

提前感谢您的富有洞察力的 cmets。

【问题讨论】:

  • 预处理器不应该关心其扩展结果的语法,编译器也不应该关心预处理器的魔法产生了它的输入。 AFAIK 这是完全合法的,虽然很可怕。
  • 代码原样严格符合 C 标准定义它,因此在这个意义上它是可移植的。正如您所注意到的,它可能不适用于自动工具。通常也不能依赖它与其他源代码一起使用,因为其他源代码可能对STARTEND 等有自己的用途。随着您作为程序员的进步,您通常会学会避免这样的杂牌。几乎没有理由删除{}。只需将 STARTEND 宏与 {} 放在一起,而不是代替它们,就可以检测例程。
  • 请注意,没有理由期望任意函数会到达 END,因为函数可能会返回 return 语句(或 longjmpexitabort等)。
  • 甚至要求非空函数不能到达END
  • 它是“可移植的”,因为每个符合标准的编译器都必须接受它。但是,它非常非常规,并且正如您所指出的,它可能会与 IDE、代码分析工具、代码格式化程序和其他尝试阅读代码的人进行不良交互。

标签: c macros c-preprocessor


【解决方案1】:

在 C 语言中使用宏是可移植的吗?

是的。

这样做有什么影响?

这些工具(?什么工具?)被破坏的含义是它们可能会停止工作并需要修补或进行一些工作。最有可能的是,“这些工具”应该是固定的,因此它们不受此类结构的影响。

这种使用宏处理器是否可移植?

是的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多