C:如何根据参数编号创建具有不同行为的宏?

时间:2019-04-03 15:17:09

标签: c macros c-preprocessor variadic-macros

我想创建一个宏,该宏在具有或不具有参数时会有所不同。

例如:打印错误有两种不同的实现方式:

// 1. Print message = check code
#define PRINT_IF(wasError) \
    do { if (wasError) printf(#wasError); } while(false)

// 2. Throws an exception with formatted message
#define PRINT_TEXT_IF(wasError, format, ...) \
    do { if (wasError) printf(format, ##__VA_ARGS__); } while(false)

我想在两种情况下都使用一个宏。

我尝试过的是根据How to count the number of arguments passed to a function that accepts a variable number of arguments?的方法创建一个全局宏来检查它是否具有参数。

#define RANDOM_GUID "5c300a82-2fe8-4bd3-ad12-ef13fa7b4a82"
#define FIRST_ARG(a1, ...) a1
#define HAS_ARGS(...) FIRST_ARG(##__VA_ARGS__, RANDOM_GUID)

#define GLOBAL_PRINT_IF(wasError, ...)             \
    do {                                           \ 
      if (wasError) {                              \
        if (HAS_ARGS(##__VA_ARGS__)==RANDOM_GUID ) \
          PRINT_IF(wasError);                      \
        else                                       \
          PRINT_TEXT_IF(wasError, __VA_ARGS__);    \
      }                                            \
    } while(false)

我假设因为FIRST_ARG总是返回第一个参数,所以如果RANDOM_GUID为空,它将返回##__VA_ARGS__

但是此代码无法与error: pasting "." and "red" does not give a valid preprocessing token一起编译。 我尝试过在##之前玩__VA_ARGS__,但是在expected primary-expression before ‘==’ token时失败了 符合

if (HAS_ARGS(__VA_ARGS__)==RANDOM_GUID )

那么,我在做什么错?如何正确处理?

1 个答案:

答案 0 :(得分:1)

  1. 首先查看如何在可变参数中获取参数数量here
  2. 然后,当您知道如何获取参数数量时,您可以轻松地 检查此数字是否为0

如果此代码段为0,则此段返回参数事件的数量:

('alias1.test123.com', [], ['192.168.11.1'])

第二个片段很容易完成工作

#include <stdio.h>

#define PRINT(...)  (printf("%d\n", sizeof((int[]){__VA_ARGS__})/sizeof(int)))

int main(void)
{
    PRINT();
    PRINT(1,1);
    PRINT(1,1,1,1);
    return 0;
}