如何可视化 C/C++ #define 指令?

Posted

技术标签:

【中文标题】如何可视化 C/C++ #define 指令?【英文标题】:How can C/C++ #define directives be visualised? 【发布时间】:2019-02-27 09:18:11 【问题描述】:

我正在寻找可视化 #define 效果的方法 - 例如,编译器看不到的代码以不同的颜色显示。

主要是视觉工作室,但很高兴了解其他环境? 理想情况下,编译器也可以看到代码,但不会运行。

【问题讨论】:

如果您的 IDE 能够理解文件的编译方式,那么它应该能够做到这一点。可能 CLion 也可以做到这一点。 大多数现代 IDE 都具有某种形式的语法高亮功能,可以识别预处理器指令。我不知道任何会做你想做的事。实际上,识别已被预处理器删除的代码的逻辑计算成本太高而无法在 IDE 中运行(减慢输入的回显等),并且可能经常出错而无法使用。许多 IDE 确实可以处理一些简单的情况(例如,将 #ifdef 0#endif 中包裹的文本变灰),但您所寻求的远不止这些。主要提示:不要过度依赖预处理器。 @Peter 至少 Visual Studio 2015 及更高版本可以正确执行此操作。我不同意让预处理器在源文件上运行(隐含地,它的包含)是昂贵的。当然,您不想在每次击键后都这样做,但这是非常简单的事情。 我不明白关于 Visual Studio 的问题。它already does exactly what you ask for,那么问题是什么?通过this随机问答,它至少从 VS2005 开始就存在,并且从 VS2010 开始工作得更好。 @MaxLanghof - 我没有说运行预处理器的成本很高。我说过描述它如何更改代码的逻辑是为了识别和显示/突出显示增量。对于简单的情况,可以。但是对于进行令牌粘贴、字符串化等操作的宏,“已删除”的概念要模糊得多。预处理器还可以做很多其他事情。 【参考方案1】:

一种方法是在预处理后查看源代码,使用gcc(对于C)或g++(对于c++)只需使用选项-E

例如拥有文件p.cc

#ifdef FOO
# define BAR 1
#else
# define BAR 2
#endif

int main()

  return BAR;

如果我不定义 FOO 我有:

/tmp % gcc -E p.cc
# 1 "p.cc"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "p.cc"

int main()

  return 2;

如果我定义 FOO 我有:

/tmp % gcc -DFOO -E p.cc
# 1 "p.cc"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "p.cc"

int main()

  return 1;


注意:您的源代码中可能有#include,因此在预处理后,您会从包含的文件中获得很多行,对于问题How to show 'preprocessed' code ignoring includes with GCC,我给出了绕过它们的答案。

【讨论】:

【参考方案2】:

默认情况下,Visual Studio 已经这样做了,至少从 VS2005 开始,并且从 VS2010 开始更好(通过this Q/A):

编辑:为响应另一个答案而添加:

【讨论】:

【参考方案3】:

我如何可视化 C/C++ #define's?

简答:一般您不能(请注意,您没有在问题中定义“可视化”的含义)。你真的想看看预处理的表格。使用GCC,您实际上可以使用gcc -C -E

举个例子,__TIME____LINE__preprocessor magic predefined macro__COUNT__ 也是 GCC 扩展)。您可以编码

#if __LINE__ % 2 == 0
printf("hello from line %d\n", __LINE__);
#endif

并且行为取决于该奇怪代码的位置(在偶数行或奇数行上)。

好的,这个例子是人为的,但是合法的。通过阅读 C11 标准 n1570 进行检查。

您也可以想象一些#if __TIME__[1] == '2',但可能无法编译(因为预处理器表达式不能使用[] 索引)。但是,一些if (_TIME__[5] == '2') printf("hello\n"); 会编译(并且会进行不同的优化,具体取决于您编译它的时间)。

在实践中,确实存在与上述代码几乎一样的人为设计的代码。 Linux kernel source 代码是使用多种预处理器功能的 C 代码的一个很好的示例(您可能对 coccinelle 感兴趣,这是一个知道这一点的工具)。其构建的第一步(使用make configmake menuconfig)会生成许多定义特定内核功能的标头。有成千上万个这样的配置选项(我的/boot/config-4.19.0-3-amd64 有7352 个配置选项,每一个都转换为#if 中使用的一些预处理器宏)。

【讨论】:

您的示例对所讨论的功能有何问题? i.stack.imgur.com/Fx3Du.png 它只需要整个预处理表单可用。 对于智能感知式的事物和实际的编译器也是如此(在这两种情况下,预处理单个 TU 不应该花费大量时间)。但我想我们对“可视化#defines”的含义有不同的看法。 是的,当然。

以上是关于如何可视化 C/C++ #define 指令?的主要内容,如果未能解决你的问题,请参考以下文章

C#-C#-#define条件编译

C/C++源代码可视化? [关闭]

预处理器指令#define 特定于我的机器

GPUNvidia CUDA 编程基础教程——异步流及 CUDA C/C++ 应用程序的可视化性能分析

GPUNvidia CUDA 编程基础教程——异步流及 CUDA C/C++ 应用程序的可视化性能分析

C/C++常用预编译指令介绍