如何在GCC中弃用宏?

Eri*_*ric 13 c c++ macros gcc deprecated

我知道如何使用不推荐使用的属性来弃用这样的函数:

int old_fn () __attribute__ ((deprecated));
Run Code Online (Sandbox Code Playgroud)

但是如何弃用这样的宏:

#define OLD_MACRO 1
Run Code Online (Sandbox Code Playgroud)

先感谢您.

埃里克

Aco*_*gua 12

漂亮,优雅的解决方案,但取决于启用C99(适用于gcc 4.8.2或更高版本,未在早期版本上测试):

#define DEPRECATED_MACRO1 _Pragma ("GCC warning \"'DEPRECATED_MACRO1' macro is deprecated\"") 7
#define DEPRECATED_MACRO2(...) _Pragma ("GCC warning \"'DEPRECATED_MACRO2' macro is deprecated\"") printf(__VA_ARGS__)

int main(int argc, char*argv[])
{
    int n = DEPRECATED_MACRO1;
    DEPRECATED_MACRO2("%d\n", n);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 这也适用于Clang/LLVM. (3认同)

Pau*_*l R 8

我认为你能做的最好是这样的:

#ifdef USE_DEPRECATED_MACROS
#warning using deprecated macros
#define OLD_MACRO 1
...
#endif
Run Code Online (Sandbox Code Playgroud)

这样,您强制用户例如将-DUSE_DEPRECATED_MACROS添加到其编译器选项中,并且它们会收到警告.

  • 我会这样做:`#ifndef NO_DEPRECATED_MACROS`.这样,您可以在保持头文件客户端的源兼容性的同时发出警告.然后,用户可以添加"NO_DEPRECATED_MACROS"以消除警告,而不是在他获取新头文件时他的构建中断,并且他必须阅读发行说明以找出OLD_MACRO消失的原因.当然,如果用户使用`-Werror`这一切都是相同的事情,但如果他没有那么可能那正是因为他不希望他的构建摔倒因为你正在修补警告;-) (6认同)
  • 作为一个品味问题,我宁愿在`#include`之前在其源代码中使用用户`#define USE_DEPRECATED_MACROS 1`,而不是通过命令行放入标志......但实际上,结果相同; 他们必须知道他们正在做什么,并且可以在可能的情况下将其退出(并因此失去警告).好决定! (2认同)

nat*_*ose 5

您可以确保这些宏将扩展为包含将触发属性((不建议使用))警告的表达式的内容.

对于类似函数的宏,这很容易(特别是使用逗号运算符),但对于常量定义或非标准宏,这可能更复杂,因为这些扩展的上下文不同.我想你可以这样做:

#define DEPRECATE(name) static inline void __attribute__((deprecated)) deprecate_ ## name (void) { ; }
...
#define MAX(x, y) (DEPRECATE(MAX), x>y?x:y)
// yeah, yeah, it repeats args in the body, but it's just an example
Run Code Online (Sandbox Code Playgroud)

对于常量定义,您可能希望假设主体必须在不必生成代码的情况下进行求值,例如在函数体外部,在switch/case的目标中,或者作为函数内静态变量的初始值.

这很棘手,但你可以做很多事情.

我希望C有一个__builtin_warn(const char*)可以在编译器级别(非预处理器)工作,并使这样的事情变得更容易.

编辑

对于常量定义,您可以:

#define THREE (DEPRICATED(THREE),3)
Run Code Online (Sandbox Code Playgroud)


Yan*_*min 0

由于宏不是编译器的一部分(它们是预处理器函数),因此没有干净的方法来执行此操作。最好的情况是,将已弃用的宏放入一个充满 #warnings 的新头文件中。这当然会破坏现有代码,但这是保证引起人们对弃用的注意的一种方法。