查看扩展的 C 宏
如果我想扩展 C 宏,有哪些好的方法可以做到这一点(除了手动跟踪之外)?
例如,GTK_WIDGET_SET_FLAGS,它使用一个宏,该宏使用一个宏,该宏使用一个(或两个)宏......
我只想看到它以某种方式自动扩展,而不是搜索每个宏,每个步骤的方式。
更新
我尝试了cpp,但它似乎只做了第一次传递
:
GTK_WIDGET_SET_FLAGS(obj, 13)
我扩展了包含文件,然后:
G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END
这是由这些错误消息解释的我在stderr上得到了这个(当使用-o文件名时)
gtk/gtkwidget.h:34:21: gdk/gdk.h: No such file or directory gtk/gtkwidget.h:35:31: gtk/gtkaccelgroup.h: No such file or directory gtk/gtkwidget.h:36:27: gtk/gtkobject.h: No such file or directory gtk/gtkwidget.h:37:31: gtk/gtkadjustment.h: No such file or directory gtk/gtkwidget.h:38:26: gtk/gtkstyle.h: No such file or directory gtk/gtkwidget.h:39:29: gtk/gtksettings.h: No such file or directory gtk/gtkwidget.h:40:21: atk/atk.h: No such file or directory
gtk,atk,和gdk目录都在当前工作目录下,那么如何让cpp在其中搜索呢?
顺便说一句,gcc -E
给出与 cpp
完全相同的输出
更新 2:
通过使用 gcc -E 并使用 -I 选项传递包含目录来解决包含路径问题
If I want to expand a C macro, what are some good ways to do that (besides tracing it manually)?
For instance, GTK_WIDGET_SET_FLAGS
, it uses a macro that uses a macro that uses a macro (or two) ...
I want to just see it somehow expanded automagically, instead of searching for every macro, every step of the way.
UPDATE
I tried cpp, but it seemed to only do the first pass
on:
GTK_WIDGET_SET_FLAGS(obj, 13)
I got the include file expanded, and then:
G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END
This is explained by these error message I get this on stderr (when using -o filename)
gtk/gtkwidget.h:34:21: gdk/gdk.h: No such file or directory gtk/gtkwidget.h:35:31: gtk/gtkaccelgroup.h: No such file or directory gtk/gtkwidget.h:36:27: gtk/gtkobject.h: No such file or directory gtk/gtkwidget.h:37:31: gtk/gtkadjustment.h: No such file or directory gtk/gtkwidget.h:38:26: gtk/gtkstyle.h: No such file or directory gtk/gtkwidget.h:39:29: gtk/gtksettings.h: No such file or directory gtk/gtkwidget.h:40:21: atk/atk.h: No such file or directory
the gtk, atk, and gdk directories are all in the current working directory, so how do I let cpp search in it?
btw, gcc -E
gives the exact same output as cpp
Update2:
The include path problem is solved by using gcc -E and passing the include directory with the -I option
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
gcc 即使使用 -E 也需要头文件的路径...就像 -I _path_to_your_headers...
如果你有一个 Makefile,一般来说,你可以做的是用 gcc -E 覆盖 CC
一般来说,cpp 只是一个脚本为预处理器添加一些标志到 gcc,就像传统的...
gcc even with -E needs the path of the header files ... like -I _path_to_your_headers...
If you've a Makefile, generally, what you could do is over-riding CC with gcc -E
Generally, cpp is only a script adding some flags to gcc for the preprocessor, like traditional...
当鼠标指针悬停在标识符上(或其他方式)时,许多 IDE 会在编辑器中显示宏的扩展版本。 我知道 Eclipse/CDT 会这样做,Visual Studio 也会这样做(至少 VS 2008 会这样做)。
如果您正在追踪一个棘手的问题,让编译器生成预处理的输出可能会很有用,但对于日复一日的使用,您只想知道屏幕上的代码发生了什么,使用 IDE 是解决问题的方法。去。
Many IDEs will show you the expanded version of the macro in the editor when the mouse pointer hovers over the identifier (or some other way). I know Eclipse/CDT does this, and Visual Studio does this (at least VS 2008 does).
Having the compiler generate preprocessed output can be useful if you're tracking down a tricky problem, but for day in/day out use where you just want to know what's going on with the code on your screen,using the IDE is the way to go.
如果你使用 gcc 你也可以运行
If you use gcc you can also run
尝试在源文件上运行 cpp
Try running cpp on your source file
您只想运行编译器的预处理器阶段,负责扩展宏。 对于
gcc
,这是“gcc -E”,但我不确定其他编译器。You want to run just the preprocessor stage of your compiler, responsible for expanding macros. For
gcc
, that's "gcc -E", but I'm not sure about other compilers.您是否尝试多次运行 gcc -E 直到不再有任何宏?
Have you tried running gcc -E multiple times until there are no longer any macros?
当陷入粗略的 IDE 中时,请尝试
生成
使用 http://MicroChip 上的“mdematos”来 类似的内容。 com/forums/m724722.aspx
When trapped in a sketchy IDE, try something like
to produce
thanks to "mdematos" at http://MicroChip.com/forums/m724722.aspx
简单的方法
基本上这是我的字符串化宏:
#
是一个预处理器运算符,它用简单的单词生成字符串,所以stringify(foo)
会给你"foo"
。问题
但是,如果您在另一个类似
#define FOO some_expression
的宏上使用它,它只会扩展为"FOO"
(该宏的名称) 因为它还没有扩展。解决方案
这就是为什么我有一个特殊的宏,它首先对其进行扩展,然后将其放入该特殊的宏中:
示例
现在,如果我们采用这个稍微复杂一点的宏:
并像这样放入
stringify_m
:结果将是:
Naive Approach
Basically here's my stringification macro:
#
is a preprocessor operator that makes strings in simple words, sostringify(foo)
would give you"foo"
.Problem
But if you used it on another macro like this
#define FOO some_expression
, it would just expand into"FOO"
(the name of that macro) since it's not expanded yet.Solution
This is why I have special macro that expands it first and then puts it through that special macro:
Example
Now if we take this slightly more complex macro:
and put through
stringify_m
like this:the result would be:
在 macOS
-E
上,除了预处理之外不执行任何操作。-dD
输出#define指令和预处理结果。其他建议
示例代码
由于我们只是进行预处理,因此不需要
#include
来获取printf()
函数或其他库。 在此示例中,包含它会产生超过 4,000 行输出,而不包含它会产生不到 400 行输出。On macOS
-E
Do nothing beyond preprocessing.-dD
Output the #define directives and the result of preprocessing.Additional recommendations
Example code
Since we are only preprocessing we don’t need to
#include <stdio.h>
to have theprintf()
function or other libraries. In this example, including it will produce over 4,000 lines of output instead of less than 400 without.根据您使用的编译器,应该有一种方法可以查看 预处理器 之后的代码(是否进行宏扩展(编译器根本不知道宏)已完成。
对于 gcc,选项为 -E< /a>. 这是一个简化的示例,使用玩具代码而不是实际的 GTK+ 宏:
Depending on which compiler you use, there should be a way to see the code after the preprocessor (which does the macro expansion, macros are not known by the compiler at all) is done.
With gcc, the option is -E. Here's a simplified example, using toy code and not the actual GTK+ macro:
您可以在运行时转储宏的扩展,如下所示:
程序打印:
但是,这仅产生完整扩展。 如果您需要单个步骤,Eclipse/CDT 可以提供帮助,但前提是您教它所有使用的标头和编译器标志。
You can dump the expansion of a macro at run time like this:
The program prints:
However this yields only the full expansion. If you need single steps, Eclipse/CDT can help, but only if you teach it all the headers and compiler flags you use.
在 Visual Studio 中,您可以生成预处理器结果翻译单元文件。 您可以转到项目选项、C/C++/预处理器,并将“生成预处理文件”或“预处理到文件”设置为“是”(或使用 /P 或 /EP 编译器开关来包含或不包含行号)。
In Visual Studio, you can generate the preprocessor resulted translation unit file. You can go project options, C/C++/Preprocessor and put "Generate Preprocessed File" or "Preprocess to a File" on Yes (or use /P or /EP compiler switch to include line numbers or not).
GCC
-save-temps
与
-E
相比,此选项的一大优点是可以很容易地将其添加到任何构建脚本中,而无需对构建本身有很大干扰:main.c
,现在,除了正常输出
main.o
之外,当前工作目录还包含以下文件:main.i
是一个包含所需预处理的文件:<前><代码>#1“main.c”
#1“<内置>”
# 1 “<命令行>”
# 31 “<命令行>”
# 1 “/usr/include/stdc-predef.h” 1 3 4
# 32 “<命令行>” 2
# 1 “main.c”
int myfunc(int i) {
返回 i + 1;
}
main.s
是一个额外的好处,并且包含所需的生成程序集:<前><代码> .文件“main.c”
。文本
.globl myfunc
.type myfunc,@function
我的函数:
.LFB0:
.cfi_startproc
推q%rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
添加$1,%eax
弹出%rbp
.cfi_def_cfa 7, 8
雷特
.cfi_endproc
.LFE0:
.size myfunc, .-myfunc
.ident“GCC:(Ubuntu 8.3.0-6ubuntu1)8.3.0”
.section .note.GNU-stack,"",@progbits
文档:https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-save-temps
-save-temps =obj
如果您想对大量文件执行此操作,请考虑使用:
它将中间文件保存到与
-o
对象输出相同的目录中当前工作目录的名称,从而避免潜在的基本名称冲突。例如:
导致文件的创建:
显然,苹果计划接管世界。
与
-E
相比,此选项的优点是可以轻松地将其添加到任何构建脚本中,而不会过多干扰构建本身。-save-temps -v
关于此选项的另一个很酷的事情是,如果您添加
-v
:它实际上显示正在使用的显式文件,而不是
/tmp
下的丑陋临时文件,因此很容易确切地知道发生了什么,其中包括预处理/编译/汇编步骤:在 Ubuntu 19.04 (Disco Dingo) amd64、GCC 8.3.0 中测试。
Visual Studio Code 鼠标悬停
将鼠标悬停在宏上会自动展开它们,它往往工作得很好! 不确定是否需要正确的跨文件引用,因为我通常使用 clangd: VSCode“转到定义”不起作用
Git 源代码文件中的示例 remote.c 直接打开源目录后如下:
当我将鼠标悬停在
ALL_REV_FLAGS
上时宏:然后我还可以在悬停弹出窗口上选择文本,其中包含:
因此我们看到它既提供了其他宏方面的顶级扩展,也提供了完整的最终递归扩展。
同样在这种情况下,我们看到它跨文件工作,因为在这种情况下,定义来自文件 修订版.h。
GCC
-save-temps
The big advantage of this option over
-E
is that it is very easy to add it to any build script, without interfering much in the build itself:main.c
and now, besides the normal output
main.o
, the current working directory also contains the following files:main.i
is a contains the desired preprossessed file:main.s
is a bonus, and contains the desired generated assembly:Docs: https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-save-temps
-save-temps=obj
If you want to do it for a large number of files, consider using instead:
which saves the intermediate files to the same directory as the
-o
object output instead of the current working directory, thus avoiding potential basename conflicts.For example:
leads to the creation of files:
Clearly an Apple plot to take over the world.
The advantage of this option over
-E
is that it is easy to add it to any build script, without interfering much in the build itself.-save-temps -v
Another cool thing about this option is if you add
-v
:it actually shows the explicit files being used instead of ugly temporaries under
/tmp
, so it is easy to know exactly what is going on, which includes the preprocessing / compilation / assembly steps:Tested in Ubuntu 19.04 (Disco Dingo) amd64, GCC 8.3.0.
Visual Studio Code mouse hover
Hovering over macros automatically expands them, it tends to work very well! Not sure if proper cross file referencing is needed or not, for that I normally use clangd: VSCode "go to definition" not working
Example from the Git source code file remote.c on vscode 1.87.1, C/C++ extension v1.19.6, Ubuntu 23.10 after opening the source directory directly as:
as I hover over the
ALL_REV_FLAGS
macro:I can then also select text on the hover popup, which contains:
So we see that it gives both the toplevel expansion in terms of other macros, as well as the full final recursive expansion.
Also in this case we see that it worked across files, as in this case the definition comes from file revision.h.