【发布时间】:2009-10-28 22:33:23
【问题描述】:
在我的 C 项目中,我有五个不同的函数(同名),它们实现了一种算法,但方式不同。在编译时,我只需要选择其中一个函数。
我可以使用#define 和一堆#ifndef 来实现吗?有没有更好的方法来做到这一点?
【问题讨论】:
标签: c function c-preprocessor
在我的 C 项目中,我有五个不同的函数(同名),它们实现了一种算法,但方式不同。在编译时,我只需要选择其中一个函数。
我可以使用#define 和一堆#ifndef 来实现吗?有没有更好的方法来做到这一点?
【问题讨论】:
标签: c function c-preprocessor
可能更优雅的方法是使用 5 个不同的名称(例如 f1、f2、f3、f4、f5)定义它们,但始终使用相同的不同名称(例如 f)调用函数。然后编译类似:
gcc -Df=f1这会将任何对 f() 的调用编译为对 f1() 的调用。
【讨论】:
是的。你所做的就是在代码中这样说:
#if defined(FUNC1)
...func1 here
#elif defined(FUNC2)
...func2 here
...ect. ect.
#endif
然后在编译时添加 gcc 选项 -DFUNCX 例如:
gcc -DFUNC1 -o myprogram myfile.c
然后您可以通过更改您在 -D 选项中输入的值来选择要编译的函数。这是很常见的做法。
【讨论】:
您不能在一个翻译单元中定义两个同名的不同函数。
所以我猜你已经在不同的源文件之间分离了函数。只需在编译时包含您想要的文件......例如,使用 gcc
gcc -o testsort main.c bubble.c
gcc -o testsort main.c merge.c
gcc -o testsort main.c radix.c
bubble.c、merge.c、radix.c(和其他)中的任何一个具有相同名称的函数:
int sort(int *data, size_t len) { /* ... */ }
【讨论】:
在 C 中,这是我知道的唯一方法。 C++ 你会很幸运。
【讨论】:
如果您在单独的文件中有函数的源代码(例如,在 f1.c 和 f2.c 中),那么此方案有效:
$ cat so.c
#define STRINGIZER(x) #x
#define HEADER(x) STRINGIZER(x)
#include HEADER(SOURCE)
int main(void)
{
return(function());
}
$ cat f1.c
static int function(void)
{
return(1);
}
$ cat f2.c
static int function(void)
{
return(2);
}
$
然后我可以这样编译:
$ gcc -DSOURCE=f1.c -o so1 so.c
$ gcc -DSOURCE=f2.c -o so2 so.c
注意字符串化操作符和双宏的使用——这是标准 C 预处理器的标准习语。它允许我避免在 C 编译器命令行中加上引号;想想如果你必须写的话,使用起来会有多困难:
$ gxx -DSOURCE='"f1.c"' -o so1.c
运行so1和so2的结果是:
$ ./so1; echo $?
1
$ ./so2; echo $?
2
$
这显示了一种无需任何#ifdef 行即可实现所需结果的替代方法。
【讨论】:
ifndef 宏在编译时似乎是唯一的可能性。
您可以在运行时尝试使用函数 ptrs。
只是认为您可以在不同的文件中创建每个函数,并在需要时链接正确的函数。没有宏,只是一个 Makefile 开关。这样您就可以保持相同的签名并在链接时决定使用哪个实现。链接algo1.o或链接algo2.o...
【讨论】:
如果我是你,我将有 5 个不同的函数名,然后使用 if 语句来确定在运行时调用哪一个。
【讨论】:
C 没有重载(运算符或其他),因此没有其他方法可以做到这一点。恐怕你被预处理器命令困住了。
【讨论】:
如果你一定要坚持使用C,你可以使用函数指针,但我建议你使用C++和多态,这会帮你解决麻烦:)
【讨论】: