(如何)我可以内联特定的函数调用吗?

fou*_*ric 24 c inline function

假设我有一个在程序的多个部分中调用的函数.我们还要说我对该函数的特定调用是在一个性能极其敏感的代码段中(例如,循环迭代数千万次并且每微秒计数一次).有没有办法可以强制编译器(gcc在我的情况下)内联单个特定函数调用,而不是内联其他函数?

编辑:让我完全清楚:这个问题不是强迫 gcc(或任何其他编译器)内联所有函数调用; 相反,它是关于请求编译器内联对函数的特定调用.

Jam*_*ran 12

在C(而不是C++)中,没有标准的方法来建议应该内联函数.它只是特定于供应商的扩展.

但是你指定它,据我所知编译器将始终尝试内联每个实例,因此只使用该函数一次:

原版的:

   int MyFunc()  { /* do stuff */  }
Run Code Online (Sandbox Code Playgroud)

改成:

   inline int MyFunc_inlined()  { /* do stuff */  }

   int MyFunc()  { return MyFunc_inlined(); }
Run Code Online (Sandbox Code Playgroud)

现在,在您想要内联的位置,使用 MyFunc_inlined()

注意:上面的"inline"关键字只是gcc用于强制内联的语法的占位符.如果要信任H2CO3的删除答案,那将是:

static inline __attribute__((always_inline)) int MyFunc_inlined()  { /* do stuff */  }
Run Code Online (Sandbox Code Playgroud)

  • 有.`inline`关键字是标准C99.它确实给编译器一个关于内联的提示,它只是不强制**内联. (5认同)
  • @InkBlend:关键是要有两个版本的函数,一个具有always_inline属性,仅用于强制内联的地方,另一个没有always_inline属性,用于内联不重要的地方.为避免重复代码,只需调用always_inline版本即可创建非always_inline版本.所以代码被重用了. (5认同)

gav*_*avv 10

可以启用每个翻译单元的内联(但不是每次调用).虽然这不是一个问题的答案,并且是一个丑陋的技巧,它符合C标准,可能作为相关的东西很有趣.

诀窍是使用extern您不想内联的定义,以及extern inline您需要内联的位置.

例:

$ cat func.h 
int func();

$ cat func.c 
int func() { return 10; }

$ cat func_inline.h 
extern inline int func() { return 5; }

$ cat main.c       
#include <stdio.h>

#ifdef USE_INLINE
# include "func_inline.h"
#else
# include "func.h"
#endif

int main() { printf("%d\n", func()); return 0; }

$ gcc main.c func.c && ./a.out
10                                                // non-inlined version

$ gcc main.c func.c -DUSE_INLINE && ./a.out
10                                                // non-inlined version

$ gcc main.c func.c -DUSE_INLINE -O2 && ./a.out
5                                                 // inlined!
Run Code Online (Sandbox Code Playgroud)

您也可以使用非标准属性(例如__attribute__(always_inline))在GCC中)进行extern inline定义,而不是依赖于-O2.

顺便说一句,这个技巧用于glibc.


abh*_*iel 6

在C中强制内联函数的传统方法是根本不使用函数,而是使用像宏这样的函数.此方法将始终内联函数,但是像宏这样的函数存在一些问题.例如:

#define ADD(x, y) ((x) + (y))
printf("%d\n", ADD(2, 2));
Run Code Online (Sandbox Code Playgroud)

还有inline关键字,它在C99标准中添加到C中.值得注意的是,Microsoft的Visual C编译器不支持C99,因此您不能使用内联那个(悲惨的)编译器.内联仅向编译器提示您希望内联函数 - 它不保证它.

GCC有一个扩展,它要求编译器内联函数.

inline __attribute__((always_inline)) int add(int x, int y) {
    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

为了使这个更干净,您可能想要使用宏:

#define ALWAYS_INLINE inline __attribute__((always_inline))
ALWAYS_INLINE int add(int x, int y) {
    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

我不知道在某些调用中强制内联函数的直接方法.但是你可以结合这样的技术:

#define ALWAYS_INLINE inline __attribute__((always_inline))
#define ADD(x, y) ((x) + (y))
ALWAYS_INLINE int always_inline_add(int x, int y) {
    return ADD(x, y);
}

int normal_add(int x, int y) {
    return ADD(x, y);
}
Run Code Online (Sandbox Code Playgroud)

或者,你可以这样:

#define ADD(x, y) ((x) + (y))
int add(int x, int y) {
    return ADD(x, y);
}

int main() {
    printf("%d\n", ADD(2,2));    // always inline
    printf("%d\n", add(2,2));    // normal function call
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

另请注意,强制函数的内联可能不会使代码更快.内联函数会导致生成更大的代码,这可能会导致更多的缓存未命中.我希望有所帮助.