【问题标题】:Printing name and value of a macro打印宏的名称和值
【发布时间】:2010-11-12 23:22:13
【问题描述】:

我有一个 C 程序,它有很多优化可以用#defines 启用或禁用。当我运行我的程序时,我想知道在编译时定义了哪些宏。

所以我正在尝试编写一个宏函数来打印宏的实际值。像这样的:

SHOW_DEFINE(X){\
  if( IS_DEFINED(X) )\
      printf("%s is defined and as the value %d\n", #X, (int)X);\
  else\
      printf("%s is not defined\n", #X);\
}

但是我不知道如何使它工作并且我怀疑这是不可能的,有没有人知道如何做到这一点?

(请注意,即使未定义宏也必须编译!)

【问题讨论】:

标签: c c-preprocessor


【解决方案1】:

只要你愿意忍受 SOMESTRING=SOMESTRING 表示 SOMESTRING 没有被定义(把它看作是令牌没有被重新定义!?!),那么下面应该做:

#include <stdio.h>

#define STR(x)   #x
#define SHOW_DEFINE(x) printf("%s=%s\n", #x, STR(x))

#define CHARLIE -6
#define FRED 1
#define HARRY FRED
#define NORBERT ON_HOLIDAY
#define WALLY

int main()
{
    SHOW_DEFINE(BERT);
    SHOW_DEFINE(CHARLIE);
    SHOW_DEFINE(FRED);
    SHOW_DEFINE(HARRY);
    SHOW_DEFINE(NORBERT);
    SHOW_DEFINE(WALLY);

return 0;
}

输出是:

BERT=BERT
CHARLIE=-6
FRED=1
HARRY=1
NORBERT=ON_HOLIDAY
WALLY=

【讨论】:

    【解决方案2】:

    编写扩展为另一个宏的宏需要预处理器在其上运行两次。
    那还没有完成。

    你可以写一个简单的文件,

    // File check-defines.c
    int printCompileTimeDefines()
    {
    #ifdef DEF1
      printf ("defined : DEF1\n");
    #else // DEF1
      printf ("undefined: DEF1\n");
    #endif // DEF1
    // and so on...
    }
    

    在此文件中使用与其他文件相同的编译时间定义行。
    在开始时调用该函数。

    如果源文件中有#DEFINE 行而不是Makefile
    将它们移动到另一个 Header 文件并在所有源文件中包含该标题,
    包括这个check-defines.c

    希望您的所有源文件都允许使用相同的定义集。
    否则,谨慎的做法是重新检查您定义的策略。


    自动生成此函数
    您可以使用M4 宏语言(实际上甚至可以使用AWK script)。
    M4 成为您的预处理器。

    【讨论】:

    • 接受 m4 答案。当您添加另一个预处理步骤时,这变得很容易。我做了 SHOW_DEFINE(X,Y,Z ... ) 这更好。然而这是有道理的,因为我需要 m4 来处理其他东西。
    【解决方案3】:
    #ifdef MYMACRO
      printf("MYMACRO defined: %d\r\n", MYMACRO);
    #endif
    

    我认为您尝试做的事情是不可能的。您在运行时询问已在编译前处理的信息。字符串“MYMACRO”在 CPP 将其扩展为您的程序中的值后没有任何意义。

    【讨论】:

    • 好吧,这是我想避免的,因为我有很多使用#ifdef #else #endif。
    【解决方案4】:

    您没有指定您使用的编译器。如果这是 gcc,gcc -E 可能会对您有所帮助,因为它会在预处理阶段之后停止,并打印预处理结果。如果你将 gcc -E 结果与原始文件进行比较,你可能会得到你想要的部分。

    【讨论】:

      【解决方案5】:

      为什么不简单地用预处理器测试它呢?

       #if defined(X)
            printf("%s is defined and as the value %d\n", #X, (int)X);
       #else
            printf("%s is not defined\n", #X);
       #endif
      

      也可以将其嵌入到另一个测试中,而不是每次都打印它:

       #if define(SHOW_DEFINE)
       #if defined(X)
            printf("%s is defined and as the value %d\n", #X, (int)X);
       #else
            printf("%s is not defined\n", #X);
       #endif
       #endif
      

      【讨论】:

      • @philippe,嗯,这就是我和 kjfletch 的建议。但他想避免写下所有这些,这就是我建议使用 M4 或 AWK 脚本的原因。
      • 这就是我现在所做的,列表永远不会是最新的,它需要一个特殊的文件来达到这个目的:(
      【解决方案6】:

      Wave library 来自 boost 也可以帮助你做你想做的事。如果你的项目足够大,我认为值得一试。它是一个 C++ 预处理器,但无论如何它们都是一样的 :)

      【讨论】:

        【解决方案7】:

        我相信您尝试做的事情是不可能的。如果您能够改变#defines 的工作方式,那么我建议您这样做:

        #define ON 1
        #define OFF 2
        
        #define OPTIMIZE_FOO ON
        #define OPTIMIZE_BAR OFF
        
        #define SHOW_DEFINE(val)\
            if(val == ON) printf(#val" is ON\n");\
            else printf(#val" is OFF\n");
        

        【讨论】:

          【解决方案8】:

          确实不可能,问题在于“未定义”部分。如果您依赖宏值来激活/停用部分代码,那么您可以简单地执行以下操作:

          #define SHOW_DEFINE(X) \
          do { \
          if (X > 0) \
              printf("%s %d\n", #X, (int)X);   \
          else \
              printf("%s not defined\n", #X);   \
          } while(0)
          

          【讨论】:

            【解决方案9】:

            根据 Chrisharris,回答我是这样做的。 虽然我的回答不是很好,但这正是我想要的。

            #define STR(x)   #x
            #define SHOW_DEFINE(x) printf("%s %s\n", #x, strcmp(STR(x),#x)!=0?"is defined":"is NOT    defined")
            

            我发现的唯一错误是define不能是#define XXX XXX(其中XXX等于XXX)。

            【讨论】:

              【解决方案10】:

              这个问题与Macro which prints an expression and evaluates it (with __STRING) 非常接近。 Chrisharris 的回答与上一个问题的回答非常接近。

              【讨论】:

                【解决方案11】:

                您可以使用初始化为 1 的整数变量。 将#define 与此变量相乘并打印变量的值。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2017-12-20
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多