【问题标题】:Preprocessor Macros which operate on macros?对宏进行操作的预处理器宏?
【发布时间】:2011-03-19 03:20:18
【问题描述】:

这是我的宏示例:

#define STR(val) #val
#define STRX(val) STR(val)
#define LINE_ STRX(__LINE__)
#define SRC_STR __FILE__":"LINE_
#define SRC_STRN SRC_STR"\n"

#define PRINT_IF(cond) ((cond)&&(printf("\""#cond"\" is true: "SRC_STRN)>=0))
#define PRINT_IFNOT(cond) ((!(cond))&&(printf("\""#cond"\" is false: "SRC_STRN)>=0))
#define PRINT_IFN PRINT_IFNOT
#define PRINT_IFEQ(a,b) PRINT_IF(a==b)

#define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
#define PRINT_INT(i) PRINT_FMT(i,%d)
#define PRINT_LONG(i) PRINT_FMT(i,%ld)
#define PRINT_UINT(i) PRINT_FMT(i,%u)
#define PRINT_ULONG(i) PRINT_FMT(i,%lu)
#define PRINT_HEX(i) PRINT_FMT(i,%x)
#define PRINT_FLT(flt) PRINT_FMT(flt,%g)
#define PRINT_PTR(ptr) PRINT_FMT(ptr,%p)
#define PRINT_STR(str) PRINT_FMT(str,%s)

我想定义另一个与此相关的宏列表,但我想避免输入所有内容。我已经写了一个例子:

#ifndef UNITTEST
#define PRINT_INT_U(x) ((void)sizeof(x))
#else
#define PRINT_INT_U(x) PRINT_INT(x)
#endif

您可以看到,当我不运行单元测试时,我希望我的 PRINT_..._U 函数评估为空,这样我就可以向它发送垃圾邮件,而不必担心它们在运行期间到处弹出调试或生产。

所以我的问题是,是否有一些疯狂的方法使用预处理器生成新的#define 语句?我的猜测是没有...

edit:我至少可以做这样的事情吗?列个清单:

INT
LONG
UINT
ULONG
HEX
FLT
PTR
STR

然后将它们全部插入到模式中

#define PRINT_%LI%_U(x) PRINT_%LI%(x)

其中%LI% 表示列表中的一项。

【问题讨论】:

    标签: macros c-preprocessor


    【解决方案1】:

    您无需更改所有PRINT_TYPE 宏的定义:因为它们都委托给PRINT_FMT,您只需更改该宏的定义。

    #ifndef UNITTEST
        #define PRINT_FMT(unused, unused) 0
    #else
        #define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
    #endif
    

    printf 返回int,因此为了保持一致性,让无操作版本具有类型int 是有意义的。)

    【讨论】:

    • 我认为编译器会警告statement has no effect 关于0; 之类的语句。您确实提出了关于我可以利用的 PRINT_FMT 依赖项的一个很好的观点。但是我仍然想要所有额外的_U 宏,所以我可以有两个版本。我仍然想在我的非单元测试调试版本中使用它们。
    • @Steven:我会简单地#define PRINT_FMT(unused, unused) 这样它就不会扩展了。
    【解决方案2】:

    这样的事情怎么样:

    #include <stdio.h>
    
    #define FLAG
    
    #ifdef FLAG
    #define SW(x,...) x##_1(__VA_ARGS__)
    #else
    #define SW(x,...) x##_0(__VA_ARGS__)
    #endif
    
    #define TEST1(a) SW(TEST1,a)
    #define TEST1_0(a) 10
    #define TEST1_1(a) 11
    
    #define TEST2(a,b) SW(TEST2,a,b)
    #define TEST2_0(a,b) 20
    #define TEST2_1(a,b) 21
    
    #define TEST3() 32
    
    int main( void ) {
    
      printf( "1. TEST1 = %i\n", TEST1(1) );
      printf( "2. TEST2 = %i\n", TEST2(1,2) );
      printf( "3. TEST3 = %i\n", TEST3() );
    
    }
    

    可以通过参数数量而不是可变参数宏来定义 SW1、SW2 等。

    我希望它足够清楚,可以定义 SW() 来普遍禁用所有 宏,取决于标志值。但是宏“定义”(通过 SW)和“实现” 仍然需要不同的名称(没有“宏重载”),而且不可能放 一个#define 到一个宏中。

    但肯定没有必要为每个宏编写单独的#ifdef。

    【讨论】:

      【解决方案3】:

      虽然不是很令人满意,但至少,下面的代码重用了 格式说明符部分。 我不确定这是否真的能帮助你,但以防万一这可能是一个提示:

      #define INT %d
      #define LONG %ld
      ...and so forth...
      
      #define PRINT(val,fmt) printf(#val" = "STRX(fmt)": "SRC_STRN,val)
      
      #ifndef UNITTEST
      #define PRINT_U(x,fmt) ((void)sizeof(x))
      #else
      #define PRINT_U(x,fmt) PRINT(x,fmt)
      #endif
      
        int i;
        long l;
        PRINT( i, INT );
        PRINT( l, LONG );
        PRINT_U( i, INT );
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-12
        • 2015-04-15
        • 1970-01-01
        • 2012-05-27
        • 2011-01-26
        • 2010-09-19
        • 2020-02-09
        相关资源
        最近更新 更多