我试图在预处理器的帮助下改变 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 :(得分: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);
答案 1 :(得分: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 ) );
答案 2 :(得分: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中的优秀设计。它似乎容易出现问题而且很难理解。但是,我希望它能解决你的目标。
答案 3 :(得分:0)
最后我添加了一个新的装饰器,它统一处理了额外的参数,并用更具描述性的名称改变了模糊的下划线。
现在它是一个更正交的设计,我可以在编译时插入和拔出行为,而不会产生运行时开销。