编译时的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用于下一级别,如果它没有被包装)。

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

PS我愿意使用Python …但这是一个驱动程序:-(

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

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

你可以使用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 ) ); 

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

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

ISO / IEC 9899:1999(E)7.1.3

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

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

 if (0) { ... } 

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

 #include  #include  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中的优秀设计。它似乎容易出现问题并且难以理解。 但是,我希望它能解决你的目标。

最后,我添加了一个新的装饰器,它统一处理了额外的参数,并通过更具描述性的名称更改了模糊的下划线。

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