2009-07-24 53 views
2

我试图在预处理器的帮助下改变C中的一些函数的行为;并且还添加可进行设置或关闭可选参数......在编译时的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)。

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

P.S.我愿意使用Python ...但是这是一个驱动程序:-(

+0

你确定你不想要可变参数函数吗? http://en.wikipedia.org/wiki/Varargs#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D – Inshallah 2009-07-24 15:59:58

+0

很确定我不想要他们!^_ ^我已经使用过它们,我非常担心丢失静态类型检查。 – fortran 2009-07-24 16:02:19

回答

0

最后我刚添加的均匀处理额外的参数和更具描述性的名称改变了晦涩下划线一个新的装饰。

现在,这是一个更正交的设计,我可以在编译时插入和拔出行为,而无需运行时间开销。

2

似乎你想使用默认参数或C中不可用的东西。这似乎是一个坏主意。在多个C的方式,在这里,如果你不想指定参数,你只是传递NULL或-1(标准)无法处理的东西。

​​
1

我觉得这可能是更接近你想要什么,但我不确定,我的理解是允许具有任意数量参数的c函数,它们是类型检查的,并且可以在编译时被删除。

让我提醒您关于使用under通过引用标准来标识分数。您可能遇到保留的标识符。但是,我不知道这种可能性。

ISO/IEC 9899:1999(E)7.1.3

- 这与 下划线和一个大写字母 或其他下划线开头的所有标识符 总是保留用于任何用途。

此解决方案需要GCC。 GCC的版本也必须支持弱符号。这个想法是让编译器使用弱符号来寻找正确的函数定义。在没有进一步的分析(GCC 4.x版肯定不会这样)编译时

if (0) { ... } 

:此外,该函数的内容是通过使用编译器应该修剪枯枝的知识,即简化。通过将不存在的可选参数定义为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.这似乎容易出现的问题和麻烦理解。不过,我希望它能实现你的目标。

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));