Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cpp:如何理解和/或调试复杂的宏?_C_Macros_C Preprocessor_Variadic Macros_Stringification - Fatal编程技术网

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

Cpp:如何理解和/或调试复杂的宏?,c,macros,c-preprocessor,variadic-macros,stringification,C,Macros,C Preprocessor,Variadic Macros,Stringification,我正在尝试学习预处理器技巧,我发现这不是那么容易(,,…) 我知道-E选项可以查看预处理器整个过程的结果,但我想知道,是否存在逐步查看结果的选项或方法。事实上,有时很难理解当一个宏调用一个调用宏的宏时会发生什么。。。在禁用上下文的机制下,绘制蓝色。。。简而言之,我想知道是否存在一种带有断点和其他工具的预处理器调试器。 (不要回答使用预处理器指令是危险的、丑陋的、可怕的,在C语言中不是很好的做法,会产生不可读的代码……我知道这一点,这不是问题所在)。是的,此工具作为的一个功能存在。我认为访问该功能

我正在尝试学习预处理器技巧,我发现这不是那么容易(,,…) 我知道-E选项可以查看预处理器整个过程的结果,但我想知道,是否存在逐步查看结果的选项或方法。事实上,有时很难理解当一个宏调用一个调用宏的宏时会发生什么。。。在禁用上下文的机制下,绘制蓝色。。。简而言之,我想知道是否存在一种带有断点和其他工具的预处理器调试器。
(不要回答使用预处理器指令是危险的、丑陋的、可怕的,在C语言中不是很好的做法,会产生不可读的代码……我知道这一点,这不是问题所在)。

是的,此工具作为的一个功能存在。我认为访问该功能的默认方式是将鼠标悬停在希望看到展开的宏上(这将显示完全展开),然后按键盘上的
F2
(出现一个弹出窗口,允许您逐步展开)

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


如果有人对如何使用此功能感到困惑,我会在Eclipse文档中找到一个教程。

查看宏错误的唯一方法是添加一个选项,该选项将在编译完成时保留临时文件。对于gcc,它是
-save temps
选项。您可以打开
.i
文件和展开的宏

IDE索引器(如Eclipse)不会有太大帮助。在错误发生之前,它们不会展开宏(与其他应答状态一样)。 这与另一个问题相关

当你使用奇怪的预处理器技巧(这是合法的)时,要求编译器生成预处理表单(例如使用
gcc-C-e
,如果使用)并查看预处理表单是很有用的

实际上,对于源文件
foo.c
,使用
gcc-c-efoo.c>foo.i
获取其预处理形式
foo.i
并查看该
foo.i
是有意义的

有时,在没有行信息的情况下获取
foo.i
也是有意义的。这里的技巧(删除以
#
开头的行中包含的行信息)是:

gcc -C -E foo.c | grep -v '^#' > foo.i
然后您可以
缩进foo.i
并编译它,例如使用
gcc-Wall-cfoo.i
;您将在预处理文件中获得错误位置,您可以理解如何获得错误位置,并返回到预处理器宏(或它们的调用)

请记住,转换主要是在文件级别进行的文本转换。不可能单独宏扩展几行(因为先前的行可能与
#一起使用
#如果
#定义
-可能在先前的中-或者像
-DNDEBUG
传递给
gcc
g++
)。关于Linux,请参见

一个已知的扩展示例是,当使用或不使用传递给编译器的
-DNDEBUG
进行编译时,其工作方式不同。
assert(i++>0)
(对编码来说是一件非常错误的事情)的意义取决于它,并说明宏扩展不能在本地完成(您可能会想象以前的某个头具有
#define NDEBUG 1
,当然,即使它的品味很差)

宏扩展依赖于上下文的另一个示例(实际上非常常见)是使用
\uuuuu LINE\uuuu


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

如果您还没有,请查看您是否对高级宏感兴趣。有关更多信息,请查看P99和BoostPP@okovko。谢谢你提供的信息。这就是我试图理解的。参见Paul FulTZ II的答案(你可以在我给你的链接中找到答案。这是Paul Fultz II在他的github页面上的宏教程:P Oops,这是我打算给你的链接。它是解释:它是否存在这样的代码块选项?否则,我将安装Eclipse。我不知道其他IDE,但几年前我在寻找这个功能时,Eclipse是我唯一找到它的地方。它只有在宏正确的情况下才能工作。否则你只能看到错误(不是很友好和解释性的)。你不能“调试”宏。这根本不是真的。它显示了所有可能的扩展,直到出现错误为止。因此,该工具非常友好且具有解释性。如果您删除了您的否决票,我将不胜感激,因为您的批评是错误的。@okovko。太好了。我安装了Eclipse,它可以在您描述的一个简单示例上工作。(
#define ABC BCD#define BCD 1 main(){int a=ABC;}
)。非常感谢,我验证了你的答案。但是我没有eclipse IDE中F2的所有步骤。这是我在使用-E选项时看到的,不是吗?如果宏不稳定,你没有任何步骤。eclipse viewer只支持(因为它使用内部索引器)若要查看正确的宏,请尝试回答该问题以改进答案。@okovko您不应发布错误答案。请在eclipse的宏视图(F2)中显示任何部分展开的不稳定宏。如果有错误,请使用-save temps,会发生什么情况?是否可以在输出(.i文件)中看到,第一步展开直到出错?看起来问题是特别要求逐步展开宏,而且问题还提到了-E选项。是否有任何命令行工具可以逐步展开宏?很高兴找到一个。当然,这是可能的,我只是认为还没有人做到。例如例如,它是在EclipseIDE中实现的(请参阅我的答案)。Eclipse允许您一步一步地查看每个扩展,而不仅仅是最终结果,就像您使用-E标志得到的那样