查看扩展的 C 宏

发布于 2024-07-24 08:34:29 字数 1051 浏览 7 评论 0原文

如果我想扩展 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

我的痛♀有谁懂 2024-07-31 08:34:30
gcc -E myfile.c
gcc -E myfile.c
陌路黄昏 2024-07-31 08:34:30

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...

假情假意假温柔 2024-07-31 08:34:30

当鼠标指针悬停在标识符上(或其他方式)时,许多 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.

始于初秋 2024-07-31 08:34:30

如果你使用 gcc 你也可以运行

cpp myfile.c

If you use gcc you can also run

cpp myfile.c
羁拥 2024-07-31 08:34:30

尝试在源文件上运行 cpp

Try running cpp on your source file

你げ笑在眉眼 2024-07-31 08:34:30

您只想运行编译器的预处理器阶段,负责扩展宏。 对于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.

冷清清 2024-07-31 08:34:30

您是否尝试多次运行 gcc -E 直到不再有任何宏?

Have you tried running gcc -E multiple times until there are no longer any macros?

一袭白衣梦中忆 2024-07-31 08:34:30

当陷入粗略的 IDE 中时,请尝试

#define DISPLAY_VALUE2(x) #x
#define DISPLAY_VALUE(x) DISPLAY_VALUE2(x)
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))

生成

…/sketch_may21a.ino: In function 'void loop()':
…/sketch_may21a.ino:10:54: note: #pragma message: #DEFINE F_CPU 16000000L
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
                                                     ^

使用 http://MicroChip 上的“mdematos”来 类似的内容。 com/forums/m724722.aspx

When trapped in a sketchy IDE, try something like

#define DISPLAY_VALUE2(x) #x
#define DISPLAY_VALUE(x) DISPLAY_VALUE2(x)
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))

to produce

…/sketch_may21a.ino: In function 'void loop()':
…/sketch_may21a.ino:10:54: note: #pragma message: #DEFINE F_CPU 16000000L
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
                                                     ^

thanks to "mdematos" at http://MicroChip.com/forums/m724722.aspx

土豪我们做朋友吧 2024-07-31 08:34:30

简单的方法

基本上这是我的字符串化宏:

#define stringify(exp) #exp

# 是一个预处理器运算符,它用简单的单词生成字符串,所以
stringify(foo) 会给你 "foo"


问题

但是,如果您在另一个类似 #define FOO some_expression 的宏上使用它,它只会扩展为 "FOO" (该宏的名称) 因为它还没有扩展。


解决方案

这就是为什么我有一个特殊的宏,它首先对其进行扩展,然后将其放入该特殊的宏中:

#define stringify_m(macro) stringify(macro)

示例

现在,如果我们采用这个稍微复杂一点的宏:

#define _padding_(size, id) char _padding##id##_ [((size) + sizeof(char) - 1) / sizeof(char)]

并像这样放入 stringify_m

stringify_m(_padding_(8, 6502))

结果将是:

"char _padding6502_ [((8) + sizeof(char) - 1) / sizeof(char)]"

Naive Approach

Basically here's my stringification macro:

#define stringify(exp) #exp

# is a preprocessor operator that makes strings in simple words, so
stringify(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:

#define stringify_m(macro) stringify(macro)

Example

Now if we take this slightly more complex macro:

#define _padding_(size, id) char _padding##id##_ [((size) + sizeof(char) - 1) / sizeof(char)]

and put through stringify_m like this:

stringify_m(_padding_(8, 6502))

the result would be:

"char _padding6502_ [((8) + sizeof(char) - 1) / sizeof(char)]"
趁年轻赶紧闹 2024-07-31 08:34:30

在 macOS

gcc -E -dD source_file.c

-E 上,除了预处理之外不执行任何操作。

-dD 输出#define指令和预处理结果。

其他建议

示例代码

#define max(A, B) ((A) > (B) ? (A) : (B))

int main(void) {
   int a = 1, b = 2;
   printf("Between %i and %i, %i is bigger\n", a, b, max(a, b));
   return 0;
}

由于我们只是进行预处理,因此不需要 #include 来获取 printf()函数或其他库。 在此示例中,包含它会产生超过 4,000 行输出,而不包含它会产生不到 400 行输出。

On macOS

gcc -E -dD source_file.c

-E Do nothing beyond preprocessing.

-dD Output the #define directives and the result of preprocessing.

Additional recommendations

Example code

#define max(A, B) ((A) > (B) ? (A) : (B))

int main(void) {
   int a = 1, b = 2;
   printf("Between %i and %i, %i is bigger\n", a, b, max(a, b));
   return 0;
}

Since we are only preprocessing we don’t need to #include <stdio.h> to have the printf() function or other libraries. In this example, including it will produce over 4,000 lines of output instead of less than 400 without.

孤独难免 2024-07-31 08:34:29

根据您使用的编译器,应该有一种方法可以查看 预处理器 之后的代码(是否进行宏扩展(编译器根本不知道宏)已完成。

对于 gcc,选项为 -E< /a>. 这是一个简化的示例,使用玩具代码而不是实际的 GTK+ 宏:

~/tmp> cat cpptest.c
#define SET_FLAGS(w, f) ((w)->flags |= (f))

int main(void)
{
        SET_FLAGS(0, 4711);

        return 0;
}
~/tmp> gcc -E cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "cpptest.c"


int main(void)
{
 ((0)->flags |= (4711));

 return 0;
}

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:

~/tmp> cat cpptest.c
#define SET_FLAGS(w, f) ((w)->flags |= (f))

int main(void)
{
        SET_FLAGS(0, 4711);

        return 0;
}
~/tmp> gcc -E cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "cpptest.c"


int main(void)
{
 ((0)->flags |= (4711));

 return 0;
}
清浅ˋ旧时光 2024-07-31 08:34:29

您可以在运行时转储宏的扩展,如下所示:

#include <stdio.h>

/*
 * generic helper macros
 */
#define CALL(macro, arguments) macro arguments
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) # __VA_ARGS__

/*
 * dumps a macro and its expansion to stdout
 * the second argument is optional and specifies the number of
 * arguments that macro takes: 0 means macro takes zero arguments
 * no second argument means macro is not function-like
 */
#define DUMP_MACRO(macro, ...) \
    do { \
        puts ( \
            "'" \
            # macro STR(DUMP_MACRO_ARGS_ ## __VA_ARGS__) \
            "' expands to '" \
            STR(CALL(macro, DUMP_MACRO_ARGS_ ## __VA_ARGS__)) \
            "'" \
        ); \
    } while (0)
/* helpers for DUMP_MACRO, add more if required */
#define DUMP_MACRO_ARGS_
#define DUMP_MACRO_ARGS_0 ()
#define DUMP_MACRO_ARGS_1 (<1>)
#define DUMP_MACRO_ARGS_2 (<1>, <2>)
#define DUMP_MACRO_ARGS_3 (<1>, <2>, <3>)

/*
 * macros to be used in examples for DUMP_MACRO
 */
#define EXAMPLE ( EXAMPLE0() << 9 )
#define EXAMPLE0() __GNUC__
#define EXAMPLE1(EXAMPLE1) EXAMPLE1
#define EXAMPLE3(EXAMPLE1, _, __) ( EXAMPLE1 ? _(__) : false )

int main() {
    /* examples */
    DUMP_MACRO(EXAMPLE);
    DUMP_MACRO(EXAMPLE0, 0);
    DUMP_MACRO(EXAMPLE1, 1);
    DUMP_MACRO(EXAMPLE3, 3);
    DUMP_MACRO(EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol));
    /* does not work for DUMP_MACRO itself, because the
       preprocessor does not allow recursion */
    DUMP_MACRO(DUMP_MACRO, 1);
    DUMP_MACRO(DUMP_MACRO, 2);
    return 0;
}

程序打印:

'EXAMPLE' expands to '( 4 << 9 )'
'EXAMPLE0()' expands to '4'
'EXAMPLE1(<1>)' expands to '<1>'
'EXAMPLE3(<1>, <2>, <3>)' expands to '( <1> ? <2>(<3>) : false )'
'EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol)' expands to '( ( 4 << 9 ) ? non_macro_symbol : false )'
'DUMP_MACRO(<1>)' expands to 'DUMP_MACRO (<1>)'
'DUMP_MACRO(<1>, <2>)' expands to 'DUMP_MACRO (<1>, <2>)'

但是,这仅产生完整扩展。 如果您需要单个步骤,Eclipse/CDT 可以提供帮助,但前提是您教它所有使用的标头和编译器标志。

You can dump the expansion of a macro at run time like this:

#include <stdio.h>

/*
 * generic helper macros
 */
#define CALL(macro, arguments) macro arguments
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) # __VA_ARGS__

/*
 * dumps a macro and its expansion to stdout
 * the second argument is optional and specifies the number of
 * arguments that macro takes: 0 means macro takes zero arguments
 * no second argument means macro is not function-like
 */
#define DUMP_MACRO(macro, ...) \
    do { \
        puts ( \
            "'" \
            # macro STR(DUMP_MACRO_ARGS_ ## __VA_ARGS__) \
            "' expands to '" \
            STR(CALL(macro, DUMP_MACRO_ARGS_ ## __VA_ARGS__)) \
            "'" \
        ); \
    } while (0)
/* helpers for DUMP_MACRO, add more if required */
#define DUMP_MACRO_ARGS_
#define DUMP_MACRO_ARGS_0 ()
#define DUMP_MACRO_ARGS_1 (<1>)
#define DUMP_MACRO_ARGS_2 (<1>, <2>)
#define DUMP_MACRO_ARGS_3 (<1>, <2>, <3>)

/*
 * macros to be used in examples for DUMP_MACRO
 */
#define EXAMPLE ( EXAMPLE0() << 9 )
#define EXAMPLE0() __GNUC__
#define EXAMPLE1(EXAMPLE1) EXAMPLE1
#define EXAMPLE3(EXAMPLE1, _, __) ( EXAMPLE1 ? _(__) : false )

int main() {
    /* examples */
    DUMP_MACRO(EXAMPLE);
    DUMP_MACRO(EXAMPLE0, 0);
    DUMP_MACRO(EXAMPLE1, 1);
    DUMP_MACRO(EXAMPLE3, 3);
    DUMP_MACRO(EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol));
    /* does not work for DUMP_MACRO itself, because the
       preprocessor does not allow recursion */
    DUMP_MACRO(DUMP_MACRO, 1);
    DUMP_MACRO(DUMP_MACRO, 2);
    return 0;
}

The program prints:

'EXAMPLE' expands to '( 4 << 9 )'
'EXAMPLE0()' expands to '4'
'EXAMPLE1(<1>)' expands to '<1>'
'EXAMPLE3(<1>, <2>, <3>)' expands to '( <1> ? <2>(<3>) : false )'
'EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol)' expands to '( ( 4 << 9 ) ? non_macro_symbol : false )'
'DUMP_MACRO(<1>)' expands to 'DUMP_MACRO (<1>)'
'DUMP_MACRO(<1>, <2>)' expands to 'DUMP_MACRO (<1>, <2>)'

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.

君勿笑 2024-07-31 08:34:29

在 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).

筑梦 2024-07-31 08:34:29

GCC -save-temps

-E 相比,此选项的一大优点是可以很容易地将其添加到任何构建脚本中,而无需对构建本身有很大干扰:

gcc -save-temps -c -o main.o main.c

main.c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

,现在,除了正常输出 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

如果您想对大量文件执行此操作,请考虑使用:

-save-temps=obj

它将中间文件保存到与 -o 对象输出相同的目录中当前工作目录的名称,从而避免潜在的基本名称冲突。

例如:

gcc -save-temps -c -o out/subdir/main.o subdir/main.c

导致文件的创建:

out/subdir/main.i
out/subdir/main.o
out/subdir/main.s

显然,苹果计划接管世界。

-E 相比,此选项的优点是可以轻松地将其添加到任何构建脚本中,而不会过多干扰构建本身。

-save-temps -v

关于此选项的另一个很酷的事情是,如果您添加 -v

gcc -save-temps -c -o main.o -v main.c

它实际上显示正在使用的显式文件,而不是/tmp 下的丑陋临时文件,因此很容易确切地知道发生了什么,其中包括预处理/编译/汇编步骤:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

在 Ubuntu 19.04 (Disco Dingo) amd64、GCC 8.3.0 中测试。

Visual Studio Code 鼠标悬停

将鼠标悬停在宏上会自动展开它们,它往往工作得很好! 不确定是否需要正确的跨文件引用,因为我通常使用 clangd: VSCode“转到定义”不起作用

Git 源代码文件中的示例 remote.c 直接打开源目录后如下:

git clone https://github.com/git/git
cd git
git checkout e09f1254c54329773904fe25d7c545a1fb4fa920
code .

当我将鼠标悬停在 ALL_REV_FLAGS 上时宏:

在此处输入图像描述

然后我还可以在悬停弹出窗口上选择文本,其中包含:

#define ALL_REV_FLAGS (((1u<<11)-1) | NOT_USER_GIVEN | TRACK_LINEAR | PULL_MERGE)

Expands to:

(((1u<<11)-1) | (1u<<25) | (1u<<26) | (1u<<15))

因此我们看到它既提供了其他宏方面的顶级扩展,也提供了完整的最终递归扩展。

同样在这种情况下,我们看到它跨文件工作,因为在这种情况下,定义来自文件 修订版.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:

gcc -save-temps -c -o main.o main.c

main.c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

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:

    # 1 "main.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 31 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 32 "<command-line>" 2
    # 1 "main.c"
    
    
    int myfunc(int i) {
        return i + 1;
    }
    
  • main.s is a bonus, and contains the desired generated assembly:

        .file   "main.c"
        .text
        .globl  myfunc
        .type   myfunc, @function
    myfunc:
    .LFB0:
        .cfi_startproc
        pushq   %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
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   myfunc, .-myfunc
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
        .section    .note.GNU-stack,"",@progbits
    

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:

-save-temps=obj

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:

gcc -save-temps -c -o out/subdir/main.o subdir/main.c

leads to the creation of files:

out/subdir/main.i
out/subdir/main.o
out/subdir/main.s

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:

gcc -save-temps -c -o main.o -v main.c

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:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

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:

git clone https://github.com/git/git
cd git
git checkout e09f1254c54329773904fe25d7c545a1fb4fa920
code .

as I hover over the ALL_REV_FLAGS macro:

enter image description here

I can then also select text on the hover popup, which contains:

#define ALL_REV_FLAGS (((1u<<11)-1) | NOT_USER_GIVEN | TRACK_LINEAR | PULL_MERGE)

Expands to:

(((1u<<11)-1) | (1u<<25) | (1u<<26) | (1u<<15))

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文