【问题标题】:How to deprecate a C pre-processor macro in GCC?如何在 GCC 中弃用 C 预处理器宏?
【发布时间】:2011-02-10 11:53:49
【问题描述】:

我知道如何使用__attribute__((deprecated))[[deprecated]] 来弃用这样的函数:

int old_fn() __attribute__ ((deprecated));
[[deprecated]] int old_fn2();

但是如何弃用这样的宏:

#define OLD_MACRO 1

【问题讨论】:

    标签: c++ c gcc macros deprecated


    【解决方案1】:

    由于宏不是编译器的一部分(它们是预处理器函数),因此没有干净的方法可以做到这一点。充其量,将不推荐使用的宏放在一个新的头文件中,其中包含#warnings。这当然会破坏现有代码,但它是保证引起人们注意弃用的一种方式。

    【讨论】:

      【解决方案2】:

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

      #ifdef USE_DEPRECATED_MACROS
      #warning using deprecated macros
      #define OLD_MACRO 1
      ...
      #endif
      

      通过这种方式,您可以强制用户使用例如将 -DUSE_DEPRECATED_MACROS 添加到他们的编译器选项中,他们会收到警告。

      【讨论】:

      • 出于个人喜好,我宁愿在#include 之前将用户#define USE_DEPRECATED_MACROS 1 放在他们的源代码中,而不是通过命令行输入标志......但实际上,结果相同无论哪种方式;他们必须知道自己在做什么,并且可以在可能的情况下退出(并因此失去警告)。好电话!
      • 我会反其道而行之:#ifndef NO_DEPRECATED_MACROS。这样,您发出警告的同时保持头文件客户端的源兼容性。然后,用户可以添加NO_DEPRECATED_MACROS 以消除警告,而不是在获取新的头文件时破坏构建,并且他必须阅读发行说明以找出 OLD_MACRO 消失的原因。当然,如果用户使用-Werror,这一切都是一样的,但如果他不这样做,那也许正是因为他不希望他的构建因为你在修改警告而崩溃;-)
      • 这不会告诉用户正在使用哪个已弃用的宏/他应该用什么替换哪些宏等。
      【解决方案3】:

      您可以确保这些宏将扩展为包含触发__attribute__((deprecated)) 警告的表达式的内容。

      对于类似函数的宏,这很容易(尤其是使用逗号运算符),但对于常量定义或非标准宏,这可能会更复杂,因为它们展开的上下文不同。 我认为你可以这样做:

      #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
      

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

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

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

      对于常量定义,您可以这样做:

      #define THREE (DEPRICATED(THREE),3)
      

      【讨论】:

      • 事实上,如果你有那个宏,你就需要弃用它。
      • @Joshua:在软件的下一个版本中不会定义THREE,但在之后的版本中,#define THREE (4)
      • "函数 'DEPRICATED' 的隐式声明在 C99 中无效"。如果我使用DEPRECATE,我会得到“Expected expression”。
      【解决方案4】:

      不错、优雅的解决方案,但取决于启用的 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;
      }
      

      【讨论】:

      • 这似乎不适用于 gcc 4.3.3。不过不错的选择。
      • @mjs 根据here_Pragma 应该从 gcc 3.0 开始支持(从 gcc 4.5 开始完全支持 C99)。您可能必须在 4.5 之前使用 -std=c99 显式启用 C99(可能甚至更晚,真的不知道 c99 何时成为 gcc 的标准......)才能使其工作。
      • @Aconcagua 我认为 _Pragma 已被识别,它只是不理解内容。但我可能错了。
      • @mjs 要查看它是否理解内容,请尝试#pragma GCC warning "'DEPRECATED_MACRO1' macro is deprecated"。这就是 _Pragma 的东西等价于...
      猜你喜欢
      • 1970-01-01
      • 2011-09-01
      • 2020-02-09
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      相关资源
      最近更新 更多