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

查看扩展的C宏

  •  44
  • hasen  · 技术社区  · 15 年前

    如果我想扩展一个C宏,有什么好方法可以做到(除了手动跟踪它)?

    例如, GTK_WIDGET_SET_FLAGS ,它使用一个宏,该宏使用一个或两个宏…

    我只想看到它以某种方式自动扩展,而不是搜索每一个宏、每一个步骤。

    更新

    我试过CPP,但似乎只是第一次通过

    关于:

    GTK_WIDGET_SET_FLAGS(obj, 13)
    

    我扩展了include文件,然后:

    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选项传递include目录来解决include路径问题。

    11 回复  |  直到 6 年前
        1
  •  56
  •   unwind    15 年前

    根据您使用的编译器,应该有一种方法来查看 preprocessor (执行宏扩展,编译器根本不知道宏)完成。

    对于GCC,选项是 -E . 下面是一个使用toy代码而不是实际的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;
    }
    
        2
  •  11
  •   marsh    8 年前

    在Visual Studio中,可以生成预处理器生成的翻译单元文件。您可以选择项目选项,C/C++ +预处理器,并将“生成预处理文件”或“预处理到文件”放在“是”上(或使用/P或/EP编译器开关,以包含行号或不)。

        3
  •  9
  •   not-a-user    9 年前

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

    #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可以提供帮助,但前提是您要教它您使用的所有头文件和编译器标志。

        4
  •  4
  •   Markus Schnell    15 年前
    gcc -E myfile.c
    
        5
  •  3
  •   qrdl    15 年前

    如果使用gcc,还可以运行

    cpp myfile.c
    
        6
  •  3
  •   Michael Burr    15 年前

    当鼠标指针悬停在标识符上(或其他方式)时,许多IDE将在编辑器中显示宏的扩展版本。我知道Eclipse/CDT可以做到这一点,而Visual Studio可以做到这一点(至少与2008年相比)。

    如果您正在跟踪一个棘手的问题,让编译器生成预处理的输出可能会很有用,但是对于日复一日的使用来说,如果您只想知道屏幕上的代码在发生什么,使用IDE是一种可行的方法。

        7
  •  3
  •   LB40    15 年前

    gcc即使有-e也需要头文件的路径…就像-我找到你的头…

    如果你有一个makefile,一般来说,你能做的就是用gcc-e来覆盖cc。

    一般来说,cpp只是一个为预处理器向gcc添加一些标志的脚本,就像传统的……

        8
  •  2
  •   Andrew Jaffe    15 年前

    你只想跑 预处理器 编译器的阶段,负责扩展宏。为了 gcc ,这是“gcc-e”,但我不确定其他编译器。

        9
  •  2
  •   Alex Brown    15 年前

    尝试在源文件上运行cpp

        10
  •  1
  •   Earlz    15 年前

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

        11
  •  0
  •   Devon    6 年前

    当被困在一个粗略的侧面时,尝试

    #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))
                                                         ^
    

    感谢“Mdematos”在 http://MicroChip.com/forums/m724722.aspx