代码之家  ›  专栏  ›  技术社区  ›  Stef1611

Cpp:如何理解和/或调试复杂的宏?

  •  2
  • Stef1611  · 技术社区  · 6 年前

    我正在尝试学习我发现不太容易的预处理器技巧( Can we have recursive macros? , Is there a way to use C++ preprocessor stringification on variadic macro arguments? , C++ preprocessor __VA_ARGS__ number of arguments , Variadic macro trick

    我知道-E选项可以查看预处理器整个过程的结果,但我想知道,是否存在逐步查看结果的选项或方法。事实上,有时很难理解当一个宏调用一个调用宏的宏时会发生什么。。。在禁用上下文的机制下,绘制蓝色。。。简而言之,我想知道是否存在一种带有断点和其他工具的预处理器调试器。

    (不要回答使用预处理器指令是危险的、丑陋的、可怕的,在C语言中不是很好的实践,产生不可读的代码……我知道这一点,这不是问题所在)。

    3 回复  |  直到 4 年前
        1
  •  2
  •   okovko Sergey Kolesnik    6 年前

    是的,此工具作为的功能存在 Eclipse IDE . 我认为访问该功能的默认方式是将鼠标悬停在希望看到展开的宏上(这将显示完全展开),然后按 F2

    当我使用这个工具来了解更多有关宏的信息时,它非常有用。只要稍加练习,你就不再需要它了。

    如果有人对如何使用这个特性感到困惑,我找到了一个关于Eclipse文档的教程 here .

        2
  •  1
  •   Basile Starynkevitch    6 年前

    answer

    当您使用奇怪的预处理器技巧(这是合法的)时,请编译器生成预处理表单(例如使用 gcc -C -E 如果使用 GCC

    实际上,对于源文件 foo.c 获取它的预处理表单(有时)是有意义的 foo.i 具有 gcc -C -E foo.c > foo.i .

    有时候,这甚至是有道理的 没有线路信息。这里的技巧是(删除以开头的行中包含的行信息 # )将要做的是:

    gcc -C -E foo.c | grep -v '^#' > foo.i
    

    那你就可以 indent foo.i gcc -Wall -c foo.i ; 您将在预处理文件中获得错误位置,您可以理解如何获得错误位置,并返回到预处理器宏(或它们的调用)。

    记住 C preprocessor 文本的 孤立地 #if 与…结合 #define -也许在以前 #include -d files -或 preprocessor options -DNDEBUG 传给 gcc g++ feature_test_macros(7)

    -DNDEBUG assert . 意义 assert(i++ > 0) (编写代码是一件非常错误的事情)依赖于它,并说明了宏扩展不能在本地完成(您可能会想象以前的某个头具有 #define NDEBUG 1 即使这当然是低级趣味)。

    另一个宏扩展依赖于上下文的示例(实际上非常常见)是使用 __LINE__ __COUNTER__ ...

    注意。你不需要Eclipse来完成所有这些,只要一个足够好的 source code editor (我的偏好是 emacs 但这是一个品味问题):对于预处理任务,您可以使用编译器。

        3
  •  0
  •   0___________    6 年前

    查看宏错误的唯一方法是添加选项,该选项将在编译完成时保留临时文件。对gcc来说是这样的 -save-temps 选项你可以打开窗户 .i

    enter image description here