Seeing expanded C macros

后端 未结 12 1101
清歌不尽
清歌不尽 2020-11-28 05:31

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

12条回答
  •  南笙
    南笙 (楼主)
    2020-11-28 05:34

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

    #include 
    
    /*
     * 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.

提交回复
热议问题