内联函数
原理
对于频繁调用的小函数,函数调用的时间开销可能已经远高于函数本身的时间开销。这时可以通过在函数的定义前面增加inline关键字,将函数定义为内联函数来降低函数调用的开销,提高程序性能。
内联函数是在编译阶段将函数体嵌入到调用该函数的语句中。GCC编译器中函数内联的相关属性如下表 GCC编译器中函数内联的相关属性所示。表格内容说明仅指定inline属性的函数不一定内联,编译器会根据程序使用的编译选项和优化等级,同时结合实际情况,比如函数体大小、函数体内是否有递归、是否为可变数目参数等来决定是否允许内联展开。
GCC内联相关的编译选项及可以使能的优化级别如下表 GCC内联相关的编译选项及可以使能的优化级别所示。
编译选项 |
优化级别 |
说明 |
---|---|---|
early-inlining |
-O0,-O1,-O2,-O3,-Os |
针对两类函数(标记为always_inline的函数和函数执行体比调用开销小的函数),在编译器执行内联分析前完成内联。 |
inline-functions-called-once |
-O1,-O2,-O3,-Os |
考虑所有被调用一次的静态函数,即使它们没有被标记为内联,也可以内联到它们的调用者中。如果集成了对给定函数的调用,则该函数本身不会作为汇编代码输出。 |
inline-small-functions |
-O2, -O3, -Os |
当函数体小于预期的函数调用代码时,将函数集成到它们的调用者中(因此程序的整体大小变小)。编译器试探性地决定哪些函数足够简单,值得以这种方式集成。此内联适用于所有函数,甚至那些未声明为内联的函数。 |
inline-functions |
-O2, -O3, -Os |
考虑所有用于内联的函数,即使它们没有被声明为内联。编译器试探性地决定哪些函数值得以这种方式集成。 如果对给定函数的所有调用都被集成,并且该函数被声明为静态,则该函数本身通常不会作为汇编代码输出。 |
详细介绍请参见GCC手册:
修改方式
修改前:
int func(int a, int b) { return (a + b)*(a + b); }
修改后:
/*建议内联*/ static inline int func(int a, int b) { return (a + b)*(a + b) ; }
或者:
/*强制内联*/ static inline __attribute__((always_inline)) int func(int a, int b) { return (a + b)*(a + b) ; }