我正在努力学习C.通过阅读一些代码,我遇到了这样的一行:
__inline__ void () ...
__inline__
是什么意思?如何将这个词放在函数前面使它与众不同?
答案 0 :(得分:36)
__inline__
是非标准扩展程序。通常情况下,它告诉编译器:“内联此函数”,但作为非标准扩展,我们不能肯定地说,除非我们知道它在哪个编译器上。
内联是删除函数调用并将其内容直接放在调用的位置。这通常会消除调用函数的开销。它并不总是最优的,因为代码膨胀(代码变得太大并且不适合缓存),因此大多数编译器将忽略所有内联指令并执行他们认为最好的操作。 这是一件好事。我们人类在这种情况下非常匮乏,并且告诉编译器如何完成它的工作通常被认为是不好的做法。
内联是一项重要的优化,尤其是在辅助函数存在的情况下。想象一个函数返回两个整数中较小的一个:
int min(int x, int y)
{
return (x < y) ? x : y;
}
如果我在我的代码中使用了这个函数,那么实际进行函数调用将是一个巨大的浪费时间。如果我有:
int a = /* some calculation */;
int b = /* some other calculation */;
int minCalc = min(a, b);
编译器内联该函数,代码将成为:
int a = /* some calculation */;
int b = /* some other calculation */;
int minCalc = (a < b) ? a : b;
这消除了调用函数的开销。从这里开始,当编译器直接使用通常隐藏在函数调用后面的代码时,可以进行更多优化。正如您所看到的,如果我有一个很大的功能并且我强制编译器在任何地方内联它,代码大小可以非常快地增长非常,并且实际上会阻碍执行速度。
有一个标准的inline
关键字用于向编译器指示应该内联的函数,但是现在大多数编译器甚至都不承认它是内联函数的提示。
但inline
有一个重要的副作用,这可能很有用。如果函数标记为inline
,则跨多个转换单元的相同函数的多个定义不是错误。相反,选择单个函数定义,抛出其他函数定义,并假设它们是相同的(由您决定实际上好吧!)。这允许您在头文件中定义一个函数,而不会有ODR违规错误的风险。
答案 1 :(得分:7)
内联是建议编译器内联函数 - 而不是为函数和call
指令生成代码块,无论在何处使用它,它都可以有效地剪切并粘贴生成的代码,无论函数在哪里调用。
这通常只是一个建议 - 虽然如果在紧密循环中调用它可以提高性能,但它通常会增加内存使用量,这通常会产生负面的性能影响。编译器将自己决定是否内联函数 - 它可能需要“程序员建议内联这一点”,但是(在大多数编译器上),简单地将函数声明为内联并不能保证它将是。
答案 2 :(得分:4)
在computer science中,内联函数是一个programming language构造,用于告诉compiler它应该对特定函数执行in-line expansion。换句话说,编译器将在代码中使用该函数的每个位置插入函数的完整主体。
如果您要编写要包含在ISO C89程序中的头文件,请编写
__inline__
而不是inline
。请参阅Alternate Keywords。
答案 3 :(得分:1)
__inline__
声明告诉编译器,无论何处调用该函数,都要“内联”该函数。内联类似于使用宏 - 代码将被扩展,就像你在调用函数的地方编写它一样。
有关详细信息,请参阅GNU docs。
答案 4 :(得分:0)
这样做的想法是,这样做可以更有效,因为它避免了函数调用的开销;但是,最终,编译器使用代码大小,指定的优化选项和一些伏都教的组合来决定是否实际尊重此提示。
伏都教位是最容易混淆的部分。 :)不一定依赖__inline__
(或更标准的内联)来工作;如果您真的关心速度,请优化您的算法或重新组织您的代码。