tags:

views:

166

answers:

9

Hi, in my C project I have five different function (with the same name) which implement one algorithm but in different ways. At compiler time I need to select only one of these functions. Can I implement this using a #define and a bunch of #ifndef? Are there better ways to do this?

+1  A: 

In C, that is the only way I know of doing this. C++ you would be in luck.

EToreo
A: 

ifndef macros seem the only possibility at compile time.

You may try with function ptrs at runtime.

Just thought that you may create each function in different file and link the proper one whenever you want. No macros, just a Makefile switch. That way you keep the same signature and decide at link time which implementation to use. Link algo1.o or link algo2.o...

Arkaitz Jimenez
+5  A: 

Yes. What you do is say this in the code:

#if defined(FUNC1)
    ...func1 here
#elif defined(FUNC2)
    ...func2 here
...ect. ect.
#endif

And then when you compile add the gcc option -DFUNCX for example:

gcc -DFUNC1 -o myprogram myfile.c

Then you can choose which function to compile in by changing the value you put in the -D option. This is very common practice.

Robert Massaioli
One minor issue is that it's possible to call multiple functions if you accidentally define both FUNCx and FUNCy. To fix this, you should use "#if defined(FUNC1)", "#elif defined(FUNC2)", etc.
R Samuel Klatchko
Good point; my mistake. Editing the code now to reflect that.
Robert Massaioli
A: 

if i were you i'd have 5 different function name then use an if statement to figure out which one to call at runtime.

John Boker
A: 

C does not have overloading (operator or otherwise) so there is no other way to do this. I am afraid you are stuck with pre-processor commands.

Muad'Dib
+14  A: 

Probably a more elegant approach would be to define them with 5 different names (e.g. f1, f2, f3, f4, f5), but always call the function using the same different name (e.g. f). Then compile with something like:

gcc -Df=f1

That will compile any calls to f() as a call to f1().

Alex R
+1 for avoiding endless #ifdef's. The compiler will optimize the unused functions out anyway.
Jurily
The compiler should optimize it out but does it actually? (Just reading this made me wonder: http://utilitybase.com/article/show/2007/04/09/225/Size+does+matter:+Optimizing+with+size+in+mind+with+GCC)
Robert Massaioli
If the functions are declared as static it might not compile
eyalm
Nice, thank you!
Federico
+2  A: 

You cannot have two different function with the same name defined within one translation unit.

So I guess you already have the functions separated between different source files. Just include the file you want when you compile ... for example, with gcc

gcc -o testsort main.c bubble.c
gcc -o testsort main.c merge.c
gcc -o testsort main.c radix.c

Where any of bubble.c, merge.c, radix.c (and others) have a function with the same name:

int sort(int *data, size_t len) { /* ... */ }
pmg
A: 

If you have the source for the functions in separate files (for my example, in f1.c and f2.c), then this scheme works:

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

Then I can compile like this:

$ gcc -DSOURCE=f1.c -o so1 so.c
$ gcc -DSOURCE=f2.c -o so2 so.c

Note the use of the stringize operator and the double-macro dance - this is a standard idiom for the Standard C Preprocessor. It allows me to avoid putting quotes in the C compiler command line; think how much harder it would be to use if you had to write:

$ gxx -DSOURCE='"f1.c"' -o so1.c

The results of running so1 and so2 were:

$ ./so1; echo $?
1
$ ./so2; echo $?
2
$

This shows an alternative way to achieve the desired result without any #ifdef lines.

Jonathan Leffler
A: 

if you must insist on using C, you can use function pointers, but I would advice you to use C++ and polymorphism, this will get you of your troubles : )

LostMohican