【问题标题】:Select a function at compile time在编译时选择一个函数
【发布时间】:2009-10-28 22:33:23
【问题描述】:

在我的 C 项目中,我有五个不同的函数(同名),它们实现了一种算法,但方式不同。在编译时,我只需要选择其中一个函数。 我可以使用#define 和一堆#ifndef 来实现吗?有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c function c-preprocessor


    【解决方案1】:

    可能更优雅的方法是使用 5 个不同的名称(例如 f1、f2、f3、f4、f5)定义它们,但始终使用相同的不同名称(例如 f)调用函数。然后编译类似:

    gcc -Df=f1

    这会将任何对 f() 的调用编译为对 f1() 的调用。

    【讨论】:

    • +1 用于避免无休止的#ifdef。无论如何,编译器都会优化未使用的函数。
    • 编译器应该优化它,但实际上是这样吗? (只是读到这让我想知道:utilitybase.com/article/show/2007/04/09/225/…
    • 如果函数被声明为静态,它可能无法编译
    【解决方案2】:

    是的。你所做的就是在代码中这样说:

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

    然后在编译时添加 gcc 选项 -DFUNCX 例如:

    gcc -DFUNC1 -o myprogram myfile.c
    

    然后您可以通过更改您在 -D 选项中输入的值来选择要编译的函数。这是很常见的做法。

    【讨论】:

    • 一个小问题是,如果您不小心同时定义了 FUNCx 和 FUNCy,可能会调用多个函数。要解决此问题,您应该使用“#if defined(FUNC1)”、“#elif defined(FUNC2)”等。
    • 好点;我的错。现在编辑代码以反映这一点。
    【解决方案3】:

    您不能在一个翻译单元中定义两个同名的不同函数。

    所以我猜你已经在不同的源文件之间分离了函数。只需在编译时包含您想要的文件......例如,使用 gcc

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

    bubble.cmerge.cradix.c(和其他)中的任何一个具有相同名称的函数:

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

    【讨论】:

      【解决方案4】:

      在 C 中,这是我知道的唯一方法。 C++ 你会很幸运。

      【讨论】:

        【解决方案5】:

        如果您在单独的文件中有函数的源代码(例如,在 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 行即可实现所需结果的替代方法。

        【讨论】:

          【解决方案6】:

          ifndef 宏在编译时似乎是唯一的可能性。

          您可以在运行时尝试使用函数 ptrs。

          只是认为您可以在不同的文件中创建每个函数,并在需要时链接正确的函数。没有宏,只是一个 Makefile 开关。这样您就可以保持相同的签名并在链接时决定使用哪个实现。链接algo1.o或链接algo2.o...

          【讨论】:

            【解决方案7】:

            如果我是你,我将有 5 个不同的函数名,然后使用 if 语句来确定在运行时调用哪一个。

            【讨论】:

              【解决方案8】:

              C 没有重载(运算符或其他),因此没有其他方法可以做到这一点。恐怕你被预处理器命令困住了。

              【讨论】:

                【解决方案9】:

                如果你一定要坚持使用C,你可以使用函数指针,但我建议你使用C++和多态,这会帮你解决麻烦:)

                【讨论】:

                  猜你喜欢
                  • 2023-02-16
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多