2

我试图在预处理器的帮助下改变C中某些函数的行为;并且还添加了可以设置为开或关的可选参数...

可选参数的基本模式很简单:

#ifdef OPT_PARAM
  #define my_func(a, b, opt) _my_func(a, b, opt)
#else
  #define my_func(a, b, opt) _my_func(a, b)
#endif

/*the rest of the code always calls "my_func" with all the params
and not the underscored version...*/

#ifdef OPT_PARAM
void _my_func(int a, int b, int opt)
#else
void _my_func(int a, int b)
#endif
{
  /*... more #ifdefs surrounding opt uses */
}

有条件地包装函数的模式是相似的,但问题是下划线开始加起来(每一级嵌套一个额外的,可以是不同的函数,或者只是下一层的#define,以防它没有被包装)。

那么,关于如何降低代码复杂性的任何想法?

PS 我愿意使用 Python ......但这是给驱动程序的 :-(

4

4 回答 4

2

似乎您想使用默认参数或 C 中不可用的东西。这似乎是个坏主意。为什么不以更 C 的方式处理事情,如果您不想指定参数,您只需传递 NULL 或 -1(标准)。

void function (int a, int b, int c) {
  if (c != -1) {
    // something
  }
}

function(a,b,-1);
function(a,b,c);
于 2009-07-24T15:55:40.687 回答
2

可以使用 C++ 编译器吗?您可以只使用(C++ 特性)函数重载。

另一种选择是

#ifdef OPT_PARAM
#  define OPT(X) , X
#else
#  define OPT(X)  
#endif

int my_func(int a, int b OPT(int opt) ) {
#ifndef OPT_PARAM
  int opt = default_value;
#endif
  ... // Rest of code
}  


...
// calling it
my_func(2, 4 OPT( 42 ) );
于 2009-07-25T01:02:41.563 回答
1

我认为这可能更接近你想要的,但我不确定。我的理解是允许具有任意数量参数的 c 函数,这些参数经过类型检查并且可以在编译时消除。

让我通过引用标准来警告您在标识符中使用下划线。您可能会遇到保留的标识符。但是,我不知道这种可能性。

ISO/IEC 9899:1999 (E) 7.1.3

— 以下划线和大写字母或另一个下划线开头的所有标识符始终保留用于任何用途。

此解决方案需要 GCC。GCC 的版本还必须支持弱符号。这个想法是允许编译器使用弱符号查找正确的函数定义。此外,通过使用编译器应该修剪死分支的知识来简化函数的内容,即:

if (0) { ... }

在编译时无需进一步分析(GCC 4.x 肯定会这样做)。通过将不存在的可选参数定义为 c 预处理器 (cpp) 符号,您可以避免在函数体中包含 cpp 条件(如果需要)。请参阅下面如何为 f_opt0 定义 opt1 和 opt2。

#include <assert.h>
#include <stdio.h>

extern void f_opt0(int a, int b) __attribute__((weak));
extern void f_opt1(int a, int b, int opt1) __attribute__((weak));
extern void f_opt2(int a, int b, int opt1, int opt2) __attribute__((weak));

#ifdef OPT0
void f_opt0(int a, int b) {
#define opt1 0
#define opt2 0
#endif
#ifdef OPT1
void f_opt1(int a, int b, int opt1) {
#define opt2 0
#endif
#ifdef OPT2
void f_opt2(int a, int b, int opt1, int opt2) {
#endif
  if (opt1) printf("opt1=%d\n", opt1);
  if (opt2) printf("opt2=%d\n", opt2);
  printf("a+b=%d\n", a+b);
  #undef opt1
  #undef opt2
}

#define f(a, b, o1, o2) \
  if (f_opt2) f_opt2(a, b, o1, o2); \
  else if (f_opt1) f_opt1(a, b, o1); \
  else if (f_opt0) f_opt0(a, b); \
  else { assert(0 && "no f() defined!"); }

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

我的测试非常有限,我不提倡这是 C 语言中的良好设计。它似乎容易出现问题并且难以理解。但是,我希望它可以解决您的目标。

于 2009-07-25T00:40:23.273 回答
0

最后,我只是添加了一个新的装饰器,它统一处理额外的参数,并用更具描述性的名称更改了晦涩的下划线。

现在它是一个更加正交的设计,我可以在编译时插入和拔出行为而没有运行时开销。

于 2009-07-27T16:34:34.067 回答