首先,你不是在用 C 编程。你是在用 C++ 编程。这是一种不同的语言。C 没有引用或类。在您的代码中,您没有使用类,而是使用了引用(无缘无故)。
其次,考虑“函数指针”的含义。它是该函数的代码地址。现在考虑“内联”的含义。这意味着该功能在机器代码中不独立存在。它的源(概念上)放在调用它的地方,并编译调用函数。所以你想获取不存在的东西的地址。
简短的回答是你不能。
你想达到什么目标?你想总是从 b 调用 foo 吗?如果是这样,您不需要间接。您可以调用内联函数并将其内联到调用站点,或者您可以调用非内联函数并生成真正的函数调用。
// a.c
double foo(int a) { return a * 3.1415926; }
// b.c
double foo(int a); // declaration, not definition.
void b(void) { printf("%f\n", foo(10)); }
int main() { b(); return 0; }
构建:
gcc -O2 -c -o a.o a.c
请注意,在编译 bc 时,编译器不知道函数 foo 做了什么,它只知道它的签名。
gcc -O2 -c -o b.o b.c
这将这两个部分链接到一个程序中,并在开头和结尾添加部分,使其可以运行它:
gcc -o program a.o b.o
区别在于效率。内联允许许多优化(直到使用参数的值来预先计算结果并完全消除代码,就像这里一样)。在无法进行此类优化的地方内联仍然可以更快,因为它消除了函数调用开销,并且可以允许更好的寄存器分配,以及使代码更有可能在缓存中。但是内联可能很糟糕,因为它会导致代码膨胀和缓存污染,从而使代码不太可能在缓存中。
如果在编译时不知道要从 b 调用哪个函数,则需要间接调用。因此,您将拥有 foo_1 和 foo_2 并且您将传递给 b 指向其中任何一个的指针,并且它将调用该指针指向的函数,而不知道它是哪一个。这会降低性能,但有时是必要的。
double foo_1(int a) { return a * 3.1415926; }
double foo_2(int a) { return a * 2.81; }
void b(double (*foo)(int)) { printf("%f\n", foo(10)); }
int main(int argc, char *argv[])
{
if (argc < 2) return;
b(argv[1][0]-48 ? &foo_1 : &foo_2);
return 0;
}
C++ 有一个特性,您可以告诉编译器从相同的源代码生成函数 b 的两个版本:一个总是调用 foo_1,另一个总是调用 foo_2。然后 foo_1 和 foo_2 可以在两个调用站点内联,而不是选择将指向 foo_1 或 foo_2 的指针传递给 b,您需要选择调用 b_with_foo_1 或 b_with_foo_2。