C Macro中的变量no参数

时间:2012-02-16 16:10:51

标签: c unix macros embedded c99

我正在编写一些特定于硬件的代码,我想使用C宏,宏定义将是这样的: -

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1) if(a[MODE][RESOURCE1] != x1) || \
                                                               (a[MODE][RESOURCE1] != y1)) \
                                                         a[MODE][RESOURCE1]=x3;

因为有时我可以分配超过1个资源,例如: -

#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) if(a[MODE][RESOURCE1] != x1) || \
                                                               (a[MODE][RESOURCE1] != y1)) \
                                                                         a[MODE][RESOURCE1]=x3;
                                                        if(a[MODE][RESOURCE2] != x1) || \
                                                               (a[MODE][RESOURCE2] != y1)) \
                                                         a[MODE][RESOURCE2]=x3;

有没有办法可以编写一个宏,它涵盖了两种情况,因为它需要可变数量的参数?

我在printf宏的宏中使用了可变数量的参数,但是我将如何通过它们各自的名称来解决这些参数,例如,如果我修改MACRO定义,例如:0 -

#define VALIDA_RESOURCE_AND_ALLOCATE(MODE,.....) 

我如何识别RESOURCE1,RESOURCE2?

3 个答案:

答案 0 :(得分:1)

你的宏中有很多重复的代码。简化它们有助于使解决方案更加明显:

#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) do {\
    VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE1); \
    VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE2); \
} while(0)

在这里,更简单的是,这只是在迭代参数列表时重复调用第一个宏。

假设您知道此处使用的数据类型将始终保持一致,您可以尝试这样的事情(未经测试并写下我的头脑):

#ifdef HARDWARE_PLATFORM_A
  static sometype args[] = {
      RESOURCE1,
      RESOURCE2,
      /* ... etc, etc */
  };
#elif defined HARDWARE_PLATFORM_B
  static sometype args[] = {
      RESOURCE10,
      RESOURCE11,
      /* ... etc, etc */
  };
/* repeat for all hardware platforms */
#endif

void initialization_function (void) {
    int i;
    for (i = 0; i < (sizeof(args) / sizeof(args[0])); ++i) {
        VALIDATE_RESOURCE_AND_ALLOCATE(MODE, args[i]);
    }
}

其中sometype是您将用于RESOURCE1RESOURCE2等的参数的数据类型。

考虑到你要做的事情的复杂性,你在写一个函数来做迭代而不是宏时要好得多。您仍然可以使用宏来创建RESOURCE列表,但不要尝试让预处理器为您执行迭代。如果您需要避免函数调用的开销(因为您将其标记为“嵌入”),您可以声明函数inline,结果应该与使用宏一样有效。但是,在此过程中,您将获得类型安全等内容。

虽然技术上可能可能使用宏执行此操作,但这将是一个令人讨厌的黑客行为,最有可能带来更多问题而非利益。使用预处理器执行复杂的程序任务很少结果很好。

另一种替代方法是使用代码生成器从文件中获取RESOURCE个参数列表,并生成包含初始化代码的.c文件。代码生成器将使用比C预处理器更强大的语言编写(这里几乎可以使用任何脚本语言)。除非你有一长串的RESOURCE,否则这可能不值得。

答案 1 :(得分:0)

你可以实现它的一种方法是不传入可变数量的参数,但坚持使用两个参数,并使第二个参数成为可以在初始化中使用的列表。例如(为清晰起见,尾部留下反斜杠):

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE, LIST)
{
    int resources[] = LIST;
    int count;
    for(count = 0; count < sizeof(resources)/sizeof(int); count++) {
        /* do stuff here for each resources[count] */
    }
}

然后你可以简单地称它为:

VALIDATE_RESOURCE_AND_ALLOCATE(MODE, { RESOURCE1, RESOURCE2 } )

注意:有一种方法可以给这只猫上皮,所以选择你喜欢的答案然后继续: - )

答案 2 :(得分:0)

这会太傻了吗? ; - )

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1,RESOURCE2)                \
if(a[MODE][RESOURCE1] != x1) || (a[MODE][RESOURCE1] != y1))                     \
a[MODE][RESOURCE1]=x3;                                      \
if((RESOURCE1 != RESOURCE2) && (a[MODE][RESOURCE2] != x1) || (a[MODE][RESOURCE2] != y1)))   \
a[MODE][RESOURCE2]=x3;

并将其称为单个资源

VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R1)

,如下两个?

VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R2)